按下 Ctrl + Alt + F<Num> 会发生什么?

use*_*765 39 linux terminal keyboard tty console

我正在寻找有关按下此组合键以更改当前终端时 Linux 中会发生什么的解释。特别是,什么软件组件拦截了这个组合键并改变了终端?是内核吗?如果是内核,您能否提供处理此问题的源文件的位置?

编辑:我想了解它在图形(X11)和基于文本的环境中是如何工作的。

gol*_*cks 36

它是内核。请记住,键盘是硬件,那里发生的一切都通过内核;在 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
[...]   
Run Code Online (Sandbox Code Playgroud)

内核源代码包含一个默认的键盘映射文件,它看起来完全像这样;对于 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);
Run Code Online (Sandbox Code Playgroud)

我从该列表中编辑了一些热门歌曲;您可以在倒数第二行看到函数签名。

所以这些是转换中涉及的事情。如果您查看调用序列,最终您会回到kbd_event()in keyboard.c。这被注册为模块的事件处理程序:

(3.12.2drivers/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);           
Run Code Online (Sandbox Code Playgroud)

因此,kbd_event()应该在实际硬件驱动程序(可能来自drivers/hid/drivers/input/)中冒泡时调用。但是,您不会看到它kbd_event在该文件之外被引用,因为它是通过函数指针注册的。

一些用于检查内核的资源

  • Linux交叉参考标识符搜索是一个伟大的工具。
  • 所述交互式Linux内核地图是一个有趣的图形前端交叉参考工具。
  • 有一些庞大的 Linux 内核邮件列表 (LKML) 的历史档案,至少可以追溯到 1995 年;其中一些未维护并且搜索功能已损坏,但gmane似乎工作得很好。人们在邮件列表上提出了很多问题,这也是开发人员之间的主要沟通方式。
  • 您可以将自己的printk行注入源代码中作为一种简单的跟踪方式(并非所有标准 C 库都可以在内核代码中使用,包括 stdio 中的 printf)。printk 的东西最终会出现在 syslog 中。

Wolfgang Mauerer 写了一本关于 2.6 内核的大书,Professional Linux Kernel Architecture,其中包含大量源代码。 Greg Kroah-Hartman是过去十年的主要开发人员之一,他也有很多事情要做。