O que acontece quando Ctrl + Alt + F <Num> é pressionado?

38

Estou procurando uma explicação do que acontece no Linux quando essa combinação de teclas é pressionada para alterar o terminal atual. Em particular, qual componente de software intercepta essa combinação de teclas e altera o terminal? É o kernel? Se for o kernel, você poderia fornecer o local do arquivo de origem que lida com isso?

Edit: Eu quero entender como isso funciona em um ambiente gráfico (X11) e baseado em texto.

user31765
fonte
1
Para esclarecer, você está pressionando essas teclas enquanto estiver no X11 (ou seja, uma sessão gráfica) ou no console de texto? A resposta é diferente.
Derobert

Respostas:

36

É o núcleo. Lembre-se de que o teclado é hardware e tudo o que acontece lá passa pelo kernel; no caso de comutação VT, ele lida com o evento completamente e não passa nada para o espaço do usuário (no entanto, acredito que exista um meio relacionado ao ioctl pelo qual os programas do espaço do usuário possam ser notificados sobre a ocorrência de um comutador que os envolva e talvez afetá-lo, que X sem dúvida faz).

O kernel possui um mapa de teclas incorporado; isso pode ser modificado durante a execução loadkeyse visualizado com 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
[...]   

A fonte do kernel contém um arquivo de mapa de teclas padrão que se parece exatamente com isso; para 3.12.2 é src/drivers/tty/vt/defkeymap.map. Você também notará que há um arquivo defkeymap.c correspondente (isso pode ser gerado com loadkeys --mktable). A manipulação está em keyboard.c(todos esses arquivos estão no mesmo diretório) que chama 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);

Eu editei alguns hits dessa lista; você pode ver a assinatura da função na segunda última linha.

Portanto, essas são as coisas envolvidas na troca. Se você olhar para a seqüência de chamadas, eventualmente, você voltar a kbd_event()nos keyboard.c. Isso é registrado como um manipulador de eventos para o módulo:

(3.12.2, drivers/tty/vt/keyboard.clinha 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);           

Portanto, kbd_event()deve ser chamado quando algo surgir do driver de hardware real (provavelmente algo de drivers/hid/ou drivers/input/). No entanto, você não o verá como kbd_eventfora desse arquivo, pois é registrado por meio de um ponteiro de função.

Alguns recursos para examinar o kernel

  • A Pesquisa de identificador de referência cruzada do Linux é uma ótima ferramenta.
  • O Interactive Linux Kernel Map é um front-end gráfico interessante para a ferramenta de referência cruzada.
  • Existem alguns arquivos históricos da enorme Linux Kernel Mailing List (LKML), que remonta a pelo menos 1995; alguns deles não são mantidos e possuem recursos de pesquisa quebrados, mas o gmane parece funcionar muito bem. As pessoas fizeram muitas perguntas na lista de e-mail e também é o principal meio de comunicação entre os desenvolvedores.
  • Você pode injetar suas próprias printklinhas na fonte como um meio simples de rastrear (nem toda a biblioteca C padrão pode ser usada no código do kernel, incluindo printf do stdio). O material printk acaba no syslog.

Wolfgang Mauerer escreveu um grande livro sobre o kernel 2.6, Professional Linux Kernel Architecture , que percorre grande parte da fonte. Greg Kroah-Hartman , um dos principais desenvolvedores da última década, também tem muitas coisas por aí.

Cachinhos Dourados
fonte
1
Obrigado, é exatamente isso que eu estava procurando. Você pode elaborar o que acontece mais cedo na cadeia? Como é chamado o código no keyboard.c quando pressionamos Ctrl + Alt + F1? keyboard.c não é o "driver do teclado" real, é?
user31765
1
Não, eu não penso assim. Tudo faz parte do driver tty, para o qual keyboard.cseria um manipulador de eventos; o "driver do teclado" em si seria de nível mais baixo - existem muitos deles drivers/input/keyboard/para itens não USB. O material USB é padronizado, portanto, haveria apenas um (provavelmente envolvendo drivers/hid/usbhid/usbkbd.c). Estou supondo que o driver do teclado seja para produzir um scancode que possa ser entregue ao vt / keyboard.c (veja getkeycode () na parte superior). Documentation/input/input.txttem algumas dicas (maravilhosamente antigas, lol).
GOLDILOCKS
PS. Muitos dos desenvolvedores do kernel estão na lista de emails do kernel do linux (LKML), que é aberta ao público, e se você se importa com seus P & Qs etc. ( tux.org/lkml ), vale a pena perguntar lá ... apenas certifique-se de configurar uma pasta imediatamente, há MUITO correio envolvido.
GOLDILOCKS
Ao inspecionar o código mais de perto, existem apenas três funções não obsoletas no keyboard.c que chamam set_console: fn_lastcons (), fn_dec_console () e fn_inc_console (). Um para ir para o último console e outro para ir para a direita ou esquerda. Portanto, ainda não entendo como set_console () é chamado quando pressionamos Ctrl + Alt + F <num>. Presumo que tenhamos que passar <num> como parâmetro para set_console () em algum lugar. Eu vejo que set_console () também aparece no vt_ioctl.c, mas isso não é apenas para o ioctl do espaço do usuário, por exemplo, do chvt? Ainda existem alguns buracos no meu entendimento.
user31765
1
Há coisas mais potencialmente relacionadas em drivers / hid. Observe também 'console_callback ()' no vt.c, que pode fazer a troca e é registrado na parte superior via DECLARE_WORK. Isso está relacionado ao planejador: lxr.free-electrons.com/ident?i=DECLARE_WORK (essa ferramenta de referência cruzada pode ser alimentada em makelinux.net/kernel_map, que você pode achar interessante); Eu diria que isso faz com que essa função seja um "loop principal" para o vt. Obviamente, o link que falta aqui é exatamente como os eventos do teclado são transmitidos.
5173 goldilocks