C'est le noyau. Gardez à l'esprit que le clavier est un matériel et que tout ce qui s'y passe passe par le noyau; dans le cas de la commutation VT, il gère l'événement entièrement lui-même et ne transmet rien à l'espace utilisateur (cependant, je pense qu'il existe un moyen lié à ioctl par lequel les programmes de l'espace utilisateur peuvent être avertis qu'un basculement se produit et peut éventuellement l'affecter, ce que X fait sans aucun doute).
Le noyau a un keymap intégré ; cela peut être modifié en cours d'exécution loadkeys
et visualisé avec 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
[...]
La source du noyau contient un fichier de keymap par défaut qui ressemble exactement à ceci; pour 3.12.2 c'est src/drivers/tty/vt/defkeymap.map
. Vous remarquerez également qu’il existe un fichier defkeymap.c correspondant (qui peut être généré avec loadkeys --mktable
). Le traitement est dans keyboard.c
(tous ces fichiers sont dans le même répertoire) qui appelle set_console()
devt.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);
J'ai édité certains hits de cette liste; vous pouvez voir la signature de la fonction sur l'avant dernière ligne.
Donc, ce sont les choses impliquées dans la commutation. Si vous regardez la séquence des appels, vous revenez éventuellement kbd_event()
à keyboard.c
. Ceci est enregistré en tant que gestionnaire d'événements pour le module:
(3.12.2 drivers/tty/vt/keyboard.c
ligne 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);
Par conséquent, kbd_event()
devrait être appelé quand quelque chose monte du pilote matériel (probablement quelque chose de drivers/hid/
ou drivers/input/
). Cependant, vous ne le verrez pas mentionné en kbd_event
dehors de ce fichier, car il est enregistré via un pointeur de fonction.
Quelques ressources pour scruter le noyau
- La recherche d'identifiants de références croisées Linux est un excellent outil.
- Le noyau Linux Interactive Map est une interface graphique intéressante à l'outil de référence croisée.
- Il existe quelques archives historiques de l’énorme liste de diffusion du noyau Linux (LKML), qui remonte au moins à 1995; certains d'entre eux ne sont pas maintenus et ont des fonctionnalités de recherche cassées, mais celle-ci semble très bien fonctionner. Les gens ont posé beaucoup de questions sur la liste de diffusion et c'est également un moyen de communication primordial entre les développeurs.
- Vous pouvez injecter vos propres
printk
lignes dans la source comme moyen simple de traçage (toutes les librairies standard C ne peuvent pas être utilisées dans le code du noyau, y compris printf from stdio). Les choses printk se retrouvent dans syslog.
Wolfgang Mauerer a écrit un très grand livre sur l' architecture noyau Linux Linux 2.6 , qui utilise une grande partie de la source. Greg Kroah-Hartman , l’un des principaux développeurs de la dernière décennie, a aussi beaucoup de choses à raconter.