È il kernel. Tieni presente che la tastiera è hardware e tutto ciò che accade lì passa attraverso il kernel; nel caso di commutazione VT, gestisce l'evento completamente da solo e non passa nulla allo spazio utente (tuttavia, credo che ci sia un mezzo correlato a ioctl mediante il quale i programmi userspace possono essere avvisati di un interruttore che li coinvolge e forse influenzarlo, che X senza dubbio fa).
Il kernel ha una keymap integrata in esso; questo può essere modificato durante l'esecuzione loadkeys
e visualizzato con 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
[...]
Il sorgente del kernel contiene un file keymap predefinito che assomiglia esattamente a questo; per 3.12.2 è src/drivers/tty/vt/defkeymap.map
. Noterai anche che esiste un file defkeymap.c corrispondente (questo può essere generato con loadkeys --mktable
). La gestione è in keyboard.c
(tutti questi file sono nella stessa directory) che chiama set_console()
davt.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);
Ho modificato alcuni hit da quell'elenco; puoi vedere la firma della funzione sull'ultima riga.
Quindi queste sono le cose coinvolte nel passaggio. Se guardate la sequenza di chiamate, finalmente si torna a kbd_event()
in keyboard.c
. Questo è registrato come un gestore eventi per il modulo:
(3.12.2 drivers/tty/vt/keyboard.c
linea 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);
Quindi, kbd_event()
dovrebbe essere chiamato quando qualcosa bolle dal vero driver hardware (probabilmente qualcosa da drivers/hid/
o drivers/input/
). Tuttavia, non lo vedrai indicato come kbd_event
esterno a quel file, poiché è registrato tramite un puntatore a funzione.
Alcune risorse per il controllo del kernel
- La Ricerca identificatore di riferimenti incrociati di Linux è un ottimo strumento.
- L' Interactive Linux Kernel Map è un interessante front end grafico per lo strumento di riferimento croce.
- Ci sono alcuni archivi storici della massiccia Linux Kernel Mailing List (LKML), che risale almeno al 1995; alcuni di essi non sono mantenuti e hanno funzionalità di ricerca rotte, ma quello di Gmane sembra funzionare molto bene. Le persone hanno posto molte domande sulla mailing list ed è anche uno dei principali mezzi di comunicazione tra gli sviluppatori.
- Puoi iniettare le tue
printk
linee nel sorgente come un semplice mezzo per tracciare (non tutto il C lib standard può essere usato nel codice del kernel, incluso printf da stdio). roba di printk finisce in syslog.
Wolfgang Mauerer ha scritto un grande libro sul kernel 2.6, Professional Linux Kernel Architecture , che analizza gran parte dei sorgenti. Greg Kroah-Hartman , uno dei principali sviluppatori dell'ultimo decennio, ha anche molte cose in giro.