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


38

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

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


1
为了明确起见,您是在X11(即图形会话)中还是在文本控制台上按下这些键?答案是不同的。
derobert

Answers:


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
[...]   

内核源代码包含一个默认的键盘映射文件,看起来像这样。对于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由于它是通过函数指针注册的,因此您不会在文件外部看到它。

检查内核的一些资源

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

Wolfgang Mauerer在2.6内核上写了一本很棒的书,即Professional Linux Kernel Architecture,它涉及很多资料。 Greg Kroah-Hartman是过去十年的主要开发人员之一,也有很多事情要做。


1
谢谢,这正是我想要的。您能否详细说明一下链中较早发生的事情?当我们按Ctrl + Alt + F1时,如何调用keyboard.c中的代码?keyboard.c不是实际的“键盘驱动程序”,是吗?
user31765 2013年

1
不,我不这么认为。这都是tty驱动程序的一部分,对于该驱动程序keyboard.c将是一个事件处理程序;“键盘驱动程序”本身将处于较低级别-其中有很多drivers/input/keyboard/用于非usb的东西。Usb东西是标准化的,因此只有一个(可能涉及drivers/hid/usbhid/usbkbd.c)。我猜想,键盘驱动程序是用于生成可传递到vt / keyboard.c 的扫描代码的(请参见其顶部的getkeycode())。 Documentation/input/input.txt有一些(非常古老,哈哈)提示。
goldilocks

PS。许多内核开发人员都在对公众开放的linux内核邮件列表(LKML)上,如果您介意P&Q等(tux.org/lkml),则值得在那里查询...只需确保您立即为其设置一个文件夹,其中涉及很多邮件。
goldilocks

在仔细检查代码后,keyboard.c中只有三个非过时的函数可以调用set_console:fn_lastcons(),fn_dec_console()和fn_inc_console()。一个用于转到最后一个控制台,另一个用于向右或向左。所以我仍然不明白当我们按下Ctrl + Alt + F <num>时如何调用set_console()。我假设我们必须在某处将<num>作为参数传递给set_console()。我也看到set_console()也出现在vt_ioctl.c中,但这不仅仅适用于用户空间(例如chvt)中的ioctl吗?我的理解仍有一些漏洞。
user31765

1
驱动程序/隐藏程序中还有更多潜在的相关内容。还要注意vt.c中的'console_callback()',它可以进行切换,并通过DECLARE_WORK在顶部注册。这与调度程序有关:lxr.free-electrons.com/ident?i=DECLARE_WORK(该交叉引用工具可以从makelinux.net/kernel_map中获取,您可能会发现它很有趣);我认为这会使该函数成为vt的“主循环”。显然,这里缺少的链接正是键盘事件的传递方式。
goldilocks 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.