Заметки о консоли. Сколько их бывает?

Виртуальная консоль, с одной стороны, — окно в систему (а в одной из следующих заметок я попытаюсь показать, что это не просто метафора), с другой же — рычаг воздействия на нее, подобный архимедову. И потому возникает вопрос: а сколько же таких окон и таких рычагов система может предоставить своему пользователю?

В одной из предыдущих заметок вскользь было упомянуто, что практически во всех современных полнофункциональных дистрибутивах Linux’а при загрузке по умолчанию активизируется шесть виртуальных консолей. Однако число это не обусловлено ничем, кроме традиции, и легко может быть изменено в любую сторону.

В отличие от FreeBSD, где максимально возможное число консолей определяется при конфигурировании ядра (и составляет для умолчального ядра GENERIC целых шестнадцать), консоли в Linux’е создаются (до определенного предела) на лету, по мере возникновения в них необходимости. Типичный пример — запуск Иксов (или приложений, использующих SVGAlib). Каждый сеанс Иксов (а командами типа startx -- :# или xinit -- :#, где # — номер Искового дисплея, их можно запустить сколько угодно, вернее, на сколько хватит ресурсов) будет открыт в своей собственной виртуальной консоли, следующей по порядку после уже используемых.

Изменить число пригодных к употреблению консолей можно, и очень легко. Ибо для активизации новой консоли в Linux’е достаточно того, чтобы на ней был запущен какой-либо (в общем случае — любой) процесс.

За запуск процессов непосредственно после старта системы до недавнего времени отвечал процесс init (/sbin/init), являющийся родительским (прямо или косвенно, через запуск пользовательских процессов) по отношению ко всем остальным процессам (во загнул-то! — но подробности несколько позднее и отдельнее). А какие конкретно процессы он запускает — определяется его конфигурационным файлом, /etc/inittab.

Отступление: нынче разрабатываются и активно употребляются в экспериментальных целях более иные схемы инициализации, но о них я говорить пока не хочу. По крайней мере, пока во всех дистрибутивах ещё сохраняется совместимость с классической SysV.

Файл /etc/inittab очень важен для системы вообще, однако детальное его рассмотрение мы отложим до лучших времен (и других заметок). Пока же для нас интересна только одна его секция, отвечающая именно за активизацию виртуальных консолей при старте. Секция эта в моей системе (Archlinux) во времена сочинения этих заметок имела вид:

c1:3:respawn:/sbin/agetty 38400 vc/1 linux

c2:3:respawn:/sbin/agetty 38400 vc/2 linux

c3:3:respawn:/sbin/agetty 38400 vc/3 linux

c4:3:respawn:/sbin/agetty 38400 vc/4 linux

c5:3:respawn:/sbin/agetty 38400 vc/5 linux

c6:3:respawn:/sbin/agetty 38400 vc/6 linux

То есть мы видим простую colon-separated таблицу о четырех полях и шести записях. Последнее, как нетрудно догадаться, соответствует “умолчальному” количеству виртуальных консолей. А значение полей — следующие: идентификатор записи, уровень (или уровни) выполнения (runlevels), для которого эта запись имеет силу, акция, выполняемая при этом, и собственно исполняемая команда (в данном случае — команда активизации консоли). Сразу оговорюсь, что в других системах значения всех полей, кроме третьего, могут быть несколько иными (или совсем другими).

Идентификатор записи может в принципе быть любым, единственное требование к нему, как к ID любой базы данных (а перед нами — не что иное, как база данных, хотя и предельно элементарная), — то есть уникальность. В большинстве систем здесь можно видеть просто порядковый номер записи, совпадающий с номером виртуальной консоли. Последнее, впрочем, отнюдь не обязательно (хотя и рекомендуется в документации).

Что такое уровень выполнения — вопрос в данном случае неуместный. Для наших сегодняшних целей достаточно знать, что это то состояние системы, в которое она приходит при нормальной загрузке по умолчанию. В моей системе такое умолчальное состояние достигается при уровне 3, в других здесь может стоять значение любого из доступных уровней. Так как runlevel 0 соответствует останову системы, runlevel 1 зарезервирован за однопользовательским режимом, когда по определению активизируется только одна виртуальная консоль, а на runlevel 6 происходит перезагрузка системы, то доступными оказываются один из runlevels в диапазоне 2-5 или даже все они — в виде 2345.

Процедуру respawn в третьем поле можно, скорее всего, увидеть в /etc/inittab из любой Linux-системы. Она обеспечивает повторный вызов другого экземпляра того же процесса, который запускается командой из четвертого поля.

Команда же в четвертом поле — это обычно вариации на тему getty, что означает “получение терминала” (get tty). Она вызывает активизацию виртуальной консоли, указанной в качестве аргумента (в нашем примере vc/?) и запуск на ней программы login, обеспечивающей авторизацию пользователя в системе, после чего замешается программой, определенной в качестве его командной оболочки по умолчанию (login shell). Причем все эти программы (getty, login, пользовательский login shell) выполняются внутри одного и того же процесса (подробности — в соответствующем разделе).

Завершение пользовательского сеанса работы приводит к смерти этого процесса, однако не вызывает деактивизации данной виртуальной консоли, так как процедура respawn обеспечивает “регенерацию” процесса getty с повторным вызовом программы login и (в случае авторизации) login shell. То есть всем определенным в /etc/inittab виртуальным консолям суждена вечная (до останова или перезагрузки системы) жизнь.

Еще несколько замечаний о содержимом четвертого поля. В приведенном примере использована команда /sbin/agetty (из пакета util-linux). Полный путь к ней указан не случайно — очевидно, что файл /etc/inittab задействуется системой раньше, чем считывается значение переменной $PATH из общесистемного или пользовательского профильного файла (типа /etc/profile или ~/.profile. Однако сама по себе команда получения терминала в других системах может быть иной — например, /sbin/mingetty или что-нибудь подобное.

Первый аргумент команды обозначает скорость соединения по последовательной линии. Очевидно, что для виртуальной консоли никакого физического смысла он не имеет и спокойно мог бы быть опущен, что обычно и делается при использовании программы /sbin/mingetty (что и не удивительно, так как mingetty и приспособлена только для работы с виртуальными терминалами). Однако в /sbin/agetty попытка удалить этот аргумент приводит к ошибке (и, соответственно, невозможности загрузки). Так что лучше придерживаться той формы вызова getty, которая принята в вашем дистрибутиве.

Следующий аргумент — файл устройства активизируемой виртуальной консоли. Обращаю внимание, что в приведенном примере полный путь к файлу устройства не используется — команда agetty автоматически добавляет к нему префикс /dev/. Однако при использовании других команд получения терминала полный путь может потребоваться.

Наконец, последний аргумент определяет тип “получаемого” командой getty терминала (в примере — стандартная linux-консоль). Он также не обязателен, однако дан мной для пущей определенности (да и вреда от него никакого). Кроме того, насколько я понимаю, указание типа обязательно, если в linux-консоли должен эмулироваться терминал какого-либо иного типа (вроде vt100 или vt220).

Теперь, зная, как описываются “изначальные” виртуальные консоли, легко догадаться, как изменить их количество. Для уменьшения оного (что несколько сэкономит ресурсы слабой машины) достаточно удалить (или закомментировать) соответствующее число строк. А для увеличения — создать должное количество новых по образу и подобию существующих, изменяя только идентификатор и имя файла устройств:

c7:2:respawn:/sbin/agetty 38400 vc/7 linux

c8:2:respawn:/sbin/agetty 38400 vc/8 linux

и так далее, вплоть до

c63:2:respawn:/sbin/agetty 38400 vc/63 linux

Ибо 63 — это максимально возможное количество виртуальных консолей. Обусловлено оно тем, что именно столько младших номеров ранее резервировалось за устройствами этого класса.

Заодно замечу, что сказанного достаточно только при использовании механизма udev. Если он не задействован, то нет гарантии, что файлы устройств tty7 и выше реально имеются в каталоге /dev. И тогда их нужно будет создать — с помощью специально к тому предназначенного сценария /dev/MAKEDEV или непосредственно командой mknod. В первом случае достаточно перейти в каталог /dev и запустить

$ ./MAKEDEV -v tty7

ответом на что будет сообщение типа

create tty7 c 4 7 root:tty 666

знаменующее успех предприятия. Если же последует сообщение об ошибке (например, потому, что создание такого устройства не предусмотрено конкретным вариантом сценария MAKEDEV), придется обратиться к команде mknod, требующей указания типа устройства, старшего и младшего номеров, а также прав доступа — за деталями отправляю к man (8) mknod.


Содержание . .

. .