Answers:
它是内核。请记住,键盘是硬件,那里发生的一切都通过内核。在VT切换的情况下,它可以完全自行处理事件,并且不会将任何事件传递给用户空间(但是,我相信有一种与ioctl相关的方法,通过该方法,可以通知用户空间程序涉及到它们的切换发生并可能影响它, X无疑会这样做)。
内核中内置了一个键盘映射。可以在运行时进行修改loadkeys
,并使用进行查看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
[...]
内核源代码包含一个默认的键盘映射文件,看起来像这样。对于3.12.2是src/drivers/tty/vt/defkeymap.map
。您还会注意到有一个对应的defkeymap.c文件(可以使用生成loadkeys --mktable
)。处理位于keyboard.c
(所有这些文件都在同一目录中),该调用set_console()
来自vt.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);
我从列表中删除了一些匹配。您可以在倒数第二行看到功能签名。
这些就是切换中涉及的事情。如果您查看通话顺序,最终您会回到kbd_event()
中keyboard.c
。这已注册为模块的事件处理程序:
(3.12.2 drivers/tty/vt/keyboard.c
行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);
因此,kbd_event()
当实际硬件驱动程序中冒出某些东西(可能来自drivers/hid/
或drivers/input/
)时,应调用。但是,kbd_event
由于它是通过函数指针注册的,因此您不会在文件外部看到它。
printk
的代码行插入到源代码中,作为一种简单的跟踪方式(并非所有标准C lib都可以在内核代码中使用,包括stdio的printf)。printk的内容以syslog结尾。Wolfgang Mauerer在2.6内核上写了一本很棒的书,即Professional Linux Kernel Architecture,它涉及很多资料。 Greg Kroah-Hartman是过去十年的主要开发人员之一,也有很多事情要做。
keyboard.c
将是一个事件处理程序;“键盘驱动程序”本身将处于较低级别-其中有很多drivers/input/keyboard/
用于非usb的东西。Usb东西是标准化的,因此只有一个(可能涉及drivers/hid/usbhid/usbkbd.c
)。我猜想,键盘驱动程序是用于生成可传递到vt / keyboard.c 的扫描代码的(请参见其顶部的getkeycode())。 Documentation/input/input.txt
有一些(非常古老,哈哈)提示。