É 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 loadkeys
e 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.c
linha 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_event
fora 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
printk
linhas 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í.