Это ядро. Имейте в виду, что клавиатура аппаратная, и все, что там происходит, проходит через ядро; в случае коммутации 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 , которая содержит множество источников. Грег Кроа-Хартман , один из главных разработчиков за последнее десятилетие, также много чего знает.