Que se passe-t-il quand on appuie sur Ctrl + Alt + F <Num>?

38

Je cherche une explication de ce qui se passe sous Linux lorsque cette combinaison de touches est pressée pour changer le terminal actuel. En particulier, quel composant logiciel intercepte cette combinaison de touches et modifie le terminal? Est-ce le noyau? Si c'est le noyau, pouvez-vous indiquer l'emplacement du fichier source qui gère cela?

Edit: je veux comprendre comment cela fonctionne dans un environnement graphique (X11) et textuel.

utilisateur31765
la source
1
Pour clarifier, appuyez-vous sur ces touches dans X11 (session graphique) ou sur la console de texte? La réponse est différente
derobert

Réponses:

36

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 loadkeyset 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.cligne 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_eventdehors 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 printklignes 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.

boucle d'or
la source
1
Merci, c'est exactement ce que je cherchais. Pouvez-vous préciser ce qui se passe plus tôt dans la chaîne? Comment le code dans keyboard.c est-il appelé quand on appuie sur Ctrl + Alt + F1? keyboard.c n'est pas le "pilote de clavier", n'est-ce pas?
user31765
1
Non je ne pense pas. Tout cela fait partie du pilote tty, pour lequel keyboard.cserait un gestionnaire d'événement; le "pilote de clavier" lui-même serait de niveau inférieur - il y en a des tas drivers/input/keyboard/pour des choses non-usb. Le contenu USB est normalisé, il n'y en aurait donc qu'un seul (impliquant probablement drivers/hid/usbhid/usbkbd.c). J'imagine que le pilote de clavier sert à produire un scancode qui peut être transmis à vt / keyboard.c (voir getkeycode () tout en haut). Documentation/input/input.txta quelques allusions (merveilleusement anciennes, lol).
goldilocks
PS La plupart des développeurs du noyau se trouvent sur la liste de diffusion du noyau de Linux (LKML) qui est ouverte au public, et si vous vous occupez de vos questions et réponses, etc. ( tux.org/lkml ), cela vaut la peine de s'y renseigner ... mis en place un dossier pour cela tout de suite, il y a beaucoup de courrier impliqué.
goldilocks
Lorsque vous examinez le code de plus près, il n'y a que trois fonctions non obsolètes dans keyboard.c qui appellent set_console: fn_lastcons (), fn_dec_console () et fn_inc_console (). Un pour aller à la dernière console et un pour aller à droite ou à gauche. Donc, je ne comprends toujours pas comment on appelle set_console () quand on appuie sur Ctrl + Alt + F <num>. Je suppose que nous devons passer <num> en tant que paramètre à set_console () quelque part. Je vois que set_console () apparaît également dans vt_ioctl.c, mais n'est-ce pas uniquement pour ioctl depuis l'espace utilisateur, par exemple depuis chvt? Il y a encore des trous dans ma compréhension.
user31765
1
Il y a plus de choses potentiellement liées dans drivers / hid. Notez également 'console_callback ()' dans vt.c, qui peut effectuer le changement et est enregistré en haut via DECLARE_WORK. Cela concerne le planificateur: lxr.free-electrons.com/ident?i=DECLARE_WORK (cet outil de références croisées peut être alimenté à partir de makelinux.net/kernel_map que vous pourriez trouver intéressant); Je suppose que cela fait de cette fonction une sorte de "boucle principale" pour le vt. Évidemment, le lien manquant ici est exactement comment les événements de clavier sont transmis.
goldilocks