Что происходит при нажатии Ctrl + Alt + F <Num>?

38

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

Редактировать: я хочу понять, как это работает как в графической (X11), так и в текстовой среде.

user31765
источник
1
Чтобы уточнить, нажимаете ли вы эти клавиши в X11 (то есть в графическом сеансе) или в текстовой консоли? Ответ другой.
Дероберт

Ответы:

36

Это ядро. Имейте в виду, что клавиатура аппаратная, и все, что там происходит, проходит через ядро; в случае коммутации VT он полностью обрабатывает событие и ничего не передает в пользовательское пространство (однако, я полагаю, что существует средство, связанное с ioctl, с помощью которого пользовательские программы могут быть уведомлены о происходящем переключении с их участием и, возможно, повлиять на него, что X без сомнения делает).

Ядро имеет встроенную карту ключей ; это можно изменить во время работы с loadkeysи просмотреть с помощью dumpkeys:

[...]
keycode  59 = F1               F13              Console_13       F25             
        alt     keycode  59 = Console_1       
        control alt     keycode  59 = Console_1       
keycode  60 = F2               F14              Console_14       F26             
        alt     keycode  60 = Console_2       
        control alt     keycode  60 = Console_2       
keycode  61 = F3               F15              Console_15       F27             
        alt     keycode  61 = Console_3       
        control alt     keycode  61 = Console_3
[...]   

Исходный код ядра содержит файл раскладки ключей по умолчанию, который выглядит именно так; для 3.12.2 это src/drivers/tty/vt/defkeymap.map. Вы также заметите, что существует соответствующий файл defkeymap.c (он может быть создан с помощью loadkeys --mktable). Обработка находится в keyboard.c(все эти файлы находятся в одном каталоге), который вызывает set_console()изvt.c :

» grep set_console *.c
keyboard.c:     set_console(last_console);
keyboard.c:     set_console(i);
keyboard.c:     set_console(i);
keyboard.c:     set_console(value);
vt.c:int set_console(int nr)
vt_ioctl.c:                     set_console(arg);

Я отредактировал некоторые хиты из этого списка; вы можете увидеть сигнатуру функции во второй последней строке.

Таковы вещи, связанные с переключением. Если вы посмотрите на последовательность звонков, в конце концов вы вернетесь kbd_event()в keyboard.c. Это зарегистрировано как обработчик события для модуля:

(3.12.2 drivers/tty/vt/keyboard.cстрока 1473)

MODULE_DEVICE_TABLE(input, kbd_ids);

static struct input_handler kbd_handler = {
    .event      = kbd_event,   <--- function pointer HERE
    .match      = kbd_match,
    .connect    = kbd_connect,
    .disconnect = kbd_disconnect,
    .start      = kbd_start,
    .name       = "kbd",
    .id_table   = kbd_ids,
};  

int __init kbd_init(void)
{

[...]

    error = input_register_handler(&kbd_handler);           

Следовательно, kbd_event()должен вызываться, когда что-то всплывает из фактического аппаратного драйвера (возможно, из-за drivers/hid/или drivers/input/). Тем не менее, вы не увидите, что он называется kbd_eventвне этого файла, поскольку он зарегистрирован через указатель функции.

Некоторые ресурсы для изучения ядра

  • Linux Ссылка Идентификатор Поиск является отличным инструментом.
  • Интерактивная Linux Kernel Карта интересный графический интерфейс для перекрестных ссылок инструмента.
  • Существует несколько исторических архивов огромного списка рассылки ядра Linux (LKML), который восходит по крайней мере к 1995 году; некоторые из них не обслуживаются и имеют неработающие функции поиска, но, похоже , этот метод работает очень хорошо. Люди задавали много вопросов в списке рассылки, и это также является основным средством общения между разработчиками.
  • Вы можете вставить свои собственные printkстроки в исходный код как простое средство трассировки (не все стандартные библиотеки Cib могут использоваться в коде ядра, включая printf из stdio). материал printk заканчивается в системном журнале.

Вольфганг Маурер (Wolfgang Mauerer) написал большую большую книгу о ядре 2.6, Professional Linux Kernel Architecture , которая содержит множество источников. Грег Кроа-Хартман , один из главных разработчиков за последнее десятилетие, также много чего знает.

лютик золотистый
источник
1
Спасибо, это именно то, что я искал. Можете ли вы уточнить, что происходит раньше в цепочке? Как вызывается код в keyboard.c, когда мы нажимаем Ctrl + Alt + F1? клавиатура.c не является «драйвером клавиатуры», не так ли?
user31765
1
Нет, я так не думаю. Это все часть драйвера tty, для которого keyboard.cбудет обработчик событий; сам "драйвер клавиатуры" был бы более низкого уровня - есть куча из них drivers/input/keyboard/для вещей, не относящихся к USB. USB материал стандартизирован, поэтому будет только один (вероятно, с участием drivers/hid/usbhid/usbkbd.c). Я предполагаю, что драйвер клавиатуры предназначен для создания скан-кода, который можно передать в vt / keyboard.c (см. Getkeycode () вверху). Documentation/input/input.txtимеет некоторые (удивительно древние, смеется) намеки.
Златовласка
PS. Многие разработчики ядра включены в почтовый список ядра Linux (LKML), который открыт для общественности, и если вы не против своих P & Q и т. Д. ( Tux.org/lkml ), то стоит поинтересоваться там ... просто убедитесь, что вы создайте для него папку прямо сейчас, там задействовано МНОГО почты.
Златовласка
После более тщательного изучения кода в клавиатурном.c обнаруживаются только три устаревшие функции, которые вызывают set_console: fn_lastcons (), fn_dec_console () и fn_inc_console (). Один для перехода к последней консоли и один для перехода вправо или влево. Поэтому я до сих пор не понимаю, как вызывается set_console (), когда мы нажимаем Ctrl + Alt + F <num>. Я предполагаю, что мы должны передать <num> в качестве параметра set_console () где-нибудь. Я вижу, что set_console () тоже возникает в vt_ioctl.c, но разве это не только для ioctl из пользовательского пространства, например из chvt? В моем понимании все еще есть дыры.
user31765
1
В драйверах / спрятано больше потенциально связанных вещей. Также обратите внимание на 'console_callback ()' в vt.c, который может переключаться и регистрируется сверху через DECLARE_WORK. Это относится к планировщику: lxr.free-electrons.com/ident?i=DECLARE_WORK (этот инструмент перекрестных ссылок можно получить с makelinux.net/kernel_map, который может вас заинтересовать); Я бы предположил, что делает эту функцию своего рода «основным циклом» для VT. Очевидно, что отсутствующее звено здесь - именно то, как проходят события клавиатуры.
Златовласка