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