繁体   English   中英

操作系统如何知道向哪个进程发送键盘中断?

[英]How does OS know to which process send a keyboard interrupt?

下面是一个简单的 c 程序(用于 Ubuntu 操作系统),它等待按下任何键盘键然后终止。

#include <cstdio>
#include <conio.h>

int main() {
    while(true) {
        if (_kbhit()) {
            printf("Key hit\n");
            return 0;
        }
    }
    return 0;
}

如果我在终端 nr 上启动这个程序。 1,只有当鼠标指向终端 1 时,程序才会对我按下键做出反应。因此,如果两个这样的程序同时作为单独的进程运行,则按下一个键最多将终止一个程序。

操作系统如何知道向哪个进程发送键盘中断?

大问题。 在您的示例中,如前所述,它没有; 取决于您对OS的定义。

在经典的 unix 系统中,GUI 由运行在用户空间中的相对常规的程序提供。 GUI(例如 X11)是唯一连接到实际键盘设备的; 并将这些键转换为 GUI 中的事件 当按键被按下时,GUI 中具有输入焦点的 window 将接收该事件。

终端仿真器是在 GUI 内运行的程序,为程序提供 1970 年代 tty 界面到 GUI。 该程序使用一种特殊类型的 tty 设备,称为伪 tty,其功能非常类似于支持终端特定功能(tc*、ioctl)的管道(2 )。 终端仿真器接收到一个 GUI 事件指示按键命中时,它会将其注入伪 tty,然后将其作为 ascii/utf-8 字符提供给程序。

GUI 通过配置选择哪个 window 具有输入事件的焦点。 有些人更喜欢地理 - 鼠标指针所在的 window 接收这些事件; 有些人更喜欢click to focus ,你必须点击 window 来确定谁有焦点。 两者都有优点和缺点; 但如果你经常在 irc/slack/... 中收到来自某人的奇怪消息,他们可能会选择点击对焦。

在没有 gui 的情况下,答案既简单又复杂。 在明显的情况下,是程序向您打印“$”提示符; 在复杂的情况下,您需要阅读会话、进程组、控制终端、作业控制

首先,这是一个直接从键盘缓冲区(又名键盘记录器)读取输入的程序:

#include <stdio.h>
#include <linux/input.h>

int main() {
    // Note: on other computers path to a keyboard buffer might differ
    const char path[] = "/dev/input/by-path/platform-i8042-serio-0-event-kbd";
    FILE* keyboard_buffer = fopen(path, "r");
    if (keyboard_buffer == NULL) {
        printf("Failed to open. Try running with root access.\n");
        return 1;
    }

    struct input_event event;
    while(1) {
        fread(&event, sizeof event, 1, keyboard_buffer);
        if (event.type == EV_KEY && event.value == 1) {
            printf("Key %d has been pressed\n", event.code);
            fclose(keyboard_buffer);
            return 0;
        }
    }
}

如果你启动这个程序并在任意位置按下键,它会立即退出,因为这里我们不是从标准输入读取键盘数据,而是从安装在文件/dev/input/by-path/platform-i8042-serio-0-event-kbd上的键盘缓冲区读取数据/dev/input/by-path/platform-i8042-serio-0-event-kbd

另一方面,您的代码使用conio.h库读取键盘事件,该事件在内部调用getchar()stdin读取:

当通过交互式 shell 执行命令时,流(即标准输入)通常连接到运行 shell 的文本终端,

一个进程的标准输入将指向与另一个进程的标准输入不同的文件。

现在操作系统(即键盘驱动程序)所做的是将按键从键盘缓冲区转发到前台进程的标准输入。 由于在您的情况下,只有一个程序将作为前台进程运行,因此按键将仅转发到 stdin 流之一。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM