Es el núcleo. Tenga en cuenta que el teclado es hardware y todo lo que sucede allí pasa a través del núcleo; en el caso del cambio de VT, maneja el evento completamente por sí mismo y no pasa nada al espacio de usuario (sin embargo, creo que hay un medio relacionado con ioctl por el cual los programas de espacio de usuario pueden ser notificados de un cambio que los involucra y tal vez lo afecte, que X sin duda lo hace).
El núcleo tiene un mapa de teclas incorporado; esto se puede modificar mientras se ejecuta con loadkeys
y ver 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
[...]
La fuente del núcleo contiene un archivo de mapa de teclas predeterminado que se ve exactamente así; para 3.12.2 es src/drivers/tty/vt/defkeymap.map
. También notará que hay un archivo defkeymap.c correspondiente (esto se puede generar con loadkeys --mktable
). El manejo está en keyboard.c
(todos estos archivos están en el mismo directorio) que llama set_console()
desdevt.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);
Edité algunos éxitos de esa lista; Puede ver la firma de la función en la segunda última línea.
Estas son las cosas involucradas en el cambio. Si nos fijamos en la secuencia de llamadas, con el tiempo se llega de nuevo a kbd_event()
en keyboard.c
. Esto está registrado como un controlador de eventos para el módulo:
(3.12.2 drivers/tty/vt/keyboard.c
línea 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);
Por lo tanto, kbd_event()
debe llamarse cuando algo surge del controlador de hardware real (probablemente algo de drivers/hid/
o drivers/input/
). Sin embargo, no verá que se mencione kbd_event
fuera de ese archivo, ya que está registrado a través de un puntero de función.
Algunos recursos para escudriñar el núcleo
- La búsqueda de identificador de referencia cruzada de Linux es una gran herramienta.
- El mapa interactivo del kernel de Linux es una interfaz gráfica interesante para la herramienta de referencia cruzada.
- Hay algunos archivos históricos de la masiva lista de correo del kernel de Linux (LKML), que se remonta al menos a 1995; algunos de ellos no se mantienen y tienen funciones de búsqueda rotas, pero el gmane parece funcionar muy bien. La gente ha hecho muchas preguntas en la lista de correo y también es un medio principal de comunicación entre los desarrolladores.
- Puede inyectar sus propias
printk
líneas en la fuente como un medio simple de rastreo (no todas las C lib estándar se pueden usar en el código del kernel, incluido printf de stdio). El material printk termina en syslog.
Wolfgang Mauerer escribió un gran libro sobre el kernel 2.6, Professional Linux Kernel Architecture , que abarca gran parte de la fuente. Greg Kroah-Hartman , uno de los principales desarrolladores de la última década, también tiene muchas cosas dando vueltas.