To jest jądro. Pamiętaj, że klawiatura jest sprzętem i wszystko, co się tam dzieje, przechodzi przez jądro; w przypadku przełączania VT obsługuje to zdarzenie całkowicie sam i nie przekazuje niczego do przestrzeni użytkownika (uważam jednak, że istnieją środki związane z ioctl, za pomocą których programy przestrzeni użytkownika mogą być powiadamiane o wystąpieniu przełączenia z nimi związanego i być może na to wpływają, co X bez wątpienia robi).
Jądro ma wbudowaną mapę klawiszy ; można to zmodyfikować podczas pracy z loadkeys
i przeglądać za pomocą 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
[...]
Źródło jądra zawiera domyślny plik mapy klawiszy, który wygląda dokładnie tak; dla 3.12.2 to src/drivers/tty/vt/defkeymap.map
. Zauważysz również, że istnieje odpowiedni plik defkeymap.c (można go wygenerować loadkeys --mktable
). Obsługa jest w keyboard.c
(wszystkie te pliki znajdują się w tym samym katalogu), który wywołuje set_console()
zvt.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);
Zredagowałem niektóre hity z tej listy; możesz zobaczyć podpis funkcji w drugim ostatnim wierszu.
Są to rzeczy związane z przełączaniem. Jeśli spojrzeć na sekwencji połączeń, w końcu wrócisz do kbd_event()
w keyboard.c
. Jest to zarejestrowane jako moduł obsługi zdarzeń dla modułu:
(3.12.2 drivers/tty/vt/keyboard.c
wiersz 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);
Dlatego kbd_event()
powinien zostać wywołany, gdy coś wyskoczy z faktycznego sterownika sprzętowego (prawdopodobnie coś z drivers/hid/
lub drivers/input/
). Jednak nie zobaczysz go nazywanego kbd_event
poza tym plikiem, ponieważ jest on rejestrowany za pomocą wskaźnika funkcji.
Niektóre zasoby do kontroli jądra
- Linux Odsyłacze Identifier Search jest doskonałym narzędziem.
- Interactive Linux Kernel mapa to ciekawy graficzny front-end do przekroju narzędzia referencyjnego.
- Istnieje kilka historycznych archiwów ogromnej listy mailingowej jądra systemu Linux (LKML), która sięga co najmniej 1995 roku; niektóre z nich nie są utrzymywane i mają zepsute funkcje wyszukiwania, ale gmane jeden działa bardzo dobrze. Ludzie zadawali wiele pytań na liście mailowej i jest to również główny środek komunikacji między programistami.
- Możesz wstrzyknąć własne
printk
linie do źródła jako prosty sposób śledzenia (nie wszystkie standardowe biblioteki C lib mogą być używane w kodzie jądra, w tym printf ze stdio). printk rzeczy kończy się w syslog.
Wolfgang Mauerer napisał świetną dużą książkę o jądrze 2.6, Professional Linux Kernel Architecture , która przechodzi przez wiele źródeł. Greg Kroah-Hartman , jeden z głównych twórców ostatniej dekady, również ma wiele do zrobienia.