Драйверы консоли

Антонио Даплас (Antonino Daplas), перевод Олега Смагина aka saturn721

2009-07-29

Оригинал: Console Drivers

В Linux имеются два общих типа драйверов консоли. Первый тип назначается ядром для всех виртуальных консолей в течении загрузки. Этот тип называется «системный драйвером», и допускается существование только одного системного драйвера. Системный драйвер постоянен и не может быть выгружен, хотя может быть неактивным.

Драйверы второго типа могут явно загружаться и выгружаться. В этом документе они будует называться «модульными драйверами». Несколько модульных драйверов могут сосуществовать в любое время с другими драйверами управления консоли, включая системный драйвер. Однако модульный драйвер не может взять управление над консолью, если она уже управляется другим модульным драйвером. (Исключение: драйверы, вызываемые через take_over_console(), успешно перехватывают управление независимо от типа драйвера, занимающего консоль.) Он может взять на себя только управление консолью, управляемой системным драйвером. Аналогично, если модульный драйвер освободит консоль, управление возьмет на себя системный драйвер.

Модульные драйверы, с точки зрения программиста, имеют вызовы:

take_over_console() — загрузить и присоединить драйвер для консоли;
give_up_console() — выгрузить и отсоединить драйвер. 

В новых ядрах также возможны следующие вызовы:

register_con_driver()
unregister_con_driver()

Если доступна sysfs, можно проанализировать содержание /sys/class/vtconsole. Оно показывает консольные выходные буферы, зарегистрированные в системе, которые называются vtcon, где число от 0 до 15. Таким образом:

ls /sys/class/vtconsole
.   ..  vtcon0  vtcon1

В каждой директории в /sys/class/vtconsole имеются три файла:

ls /sys/class/vtconsole/vtcon0
. ..  bind  name  uevent

Что означают эти файлы?

1. Файл bind доступен для чтения и записи. Он показывает статус драйвера на чтение или действие по присоединению или отсоединению драйвера к виртуальным консолям во время записи. Возможные значения:

0 — означает, что драйвер не присоединен, а если записать это значение с помощью команды echo, то драйвер отсоединяется.

1 — означает что драйвер присоединен, а если записать это значение с помощью команды echo, то драйвер присоединяется.

2. Файл name доступен только для чтения. Показывает имя драйвера в следующем формате:

cat /sys/class/vtconsole/vtcon0/name
(S) VGA+

'(S)' означает, что драйвер — системный, т.е. он не может явно присоединен или отсоединен.

'(VGA+)' — имя драйвера

cat /sys/class/vtconsole/vtcon1/name
(М) frame buffer device

В этом случае '(М)' означает модульный драйвер, который может явно присоединен или отсоединен.

3. uevent — игнорируйте этот файл

Во время отсоединения модульного драйвера освободившуюся консоль занимает системный драйвер. Присоединение, с другой стороны, присоединяет драйвер к консоли, которая ранее была занята системным драйвером.

Примечание 1: Эта возможность должна быть включена в Kconfig. По адресу:

Device Drivers -> Character devices -> Support for binding and unbinding console drivers

Примечание 2: Если какие либо виртуальные консоли находятся в режиме KD_GRAPHICS, присоединение или отсоединение недоступно. Примером приложения, которое устанавливает этот режим, является X.

Для чего нужны эти возможности? Они полезны для разработчиков драйверов консолей. Отсоединив драйвер от консоли, они могут сделать изменение в коде, пересобрать, перезагрузить и присоединить драйвер без перезагрузки ядра. Обычные пользователей за счет этих возможностей могут переключать консоль с одного драйвера на другой (framebuffer console to VGA console) или делать что-либо подобное. (Замечание: подробности см. в файле fbcon.txt в директории linux/Documentation/fb).

Замечания для разработчиков:

Вызов take_over_console() теперь заменен на:

register_con_driver()
bind_con_driver() — private function

give_up_console() — это обертка для unregister_con_driver(), и для удачного выполнения вызова драйвер должен быть полностью отсоединен. con_is_bound() проверяет, присоединен ли драйвер или нет.

Руководство для разработчиков драйверов консоли:

Для правильной работы по присоединению и отсоединению к консоли, драйвер должен соответствовать следующим правилам:

1. Все драйверы, кроме системного, должны вызываться либо через register_con_driver(), либо через take_over_console(). Вызов register_con_driver() просто добавляет драйвер во внутренний консольный список. Он не захватит на себя консоль. Выполнение take_over_console(), как следует из названия, приводит к захвату (присоединению) консоли.

2. Все ресурсы, выделенные в ходе con->con_init(), должны быть освобождены в con->con_deinit().

3. Все ресурсы, выделенные в ходе con->con_startup(), должны быть освобождены, когда драйвер, который был прежде присоединен, отсоединяется. Консольный уровень не имеет взаимодополняющего вызова к con->con_startup(), поэтому он использует драйвер, чтобы проверить, есть ли возможность освободить эти ресурсы. В этом помогает вызов con_is_bound() в con->con_deinit(). Если вызов возвращает значение false(), то можно безопасно освободить ресурсы. Этот баланс должен обеспечивается, поскольку con-> con_startup () можно вызвать еще раз, когда приходит запрос на присоединение драйвера консоли.

4. До выхода из кода драйвера убедитесь, что драйвер полностью не присоединен. Если условие выполнено, то драйвер должен вызвать unregister_con_driver () или give_up_console ().

5. unregister_con_driver() может также быть вызван условиях, в которых драйвер оказывается неспособным обрабатывать запросы к консоли. Это может случиться с фреймбуферной консолью, которая внезапна потеряла всех свои драйверы.

Современные драйвера консоли должны работать правильно, но с соединением и отсоединением у них могут возникать проблемы. С минимальными поправками можно заставить работать их правильно.