OS 如何知道向哪个进程发送键盘中断?
How does OS know to which process send a keyboard interrupt?
下面是一个简单的 c 程序(适用于 Ubuntu OS),它等待任何键盘键被按下然后终止。
#include <cstdio>
#include <conio.h>
int main() {
while(true) {
if (_kbhit()) {
printf("Key hit\n");
return 0;
}
}
return 0;
}
如果我在终端 nr 上启动这个程序。 1,仅当鼠标指向终端 1 时,程序才会对我按下按键做出反应。因此,如果两个这样的程序同时 运行 作为单独的进程,按下一个键将最多终止一个程序.
OS如何知道向哪个进程发送键盘中断?
首先,这是一个直接从键盘缓冲区读取输入的程序(a.k.a。键盘记录器):
#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
另一方面,您的代码使用 conio.h
库读取键盘事件,它在内部调用 getchar()
从 stdin:
读取
When a command is executed via an interactive shell, the streams (i.e. stdin) are typically connected to the text terminal on which the shell is running,
一个进程的标准输入将指向与另一个进程的标准输入不同的文件。
现在 OS(即键盘驱动程序)所做的是将按键从键盘缓冲区转发到前台进程的标准输入。由于在您的情况下,只有一个程序 运行 作为前台进程,因此 key-press 将仅转发到标准输入流之一。
大问题。在您的示例中,正如 所述,它 没有;取决于您对 OS.
的定义
在经典的unix系统中,GUI是由用户space中相对常规的程序运行提供的。 GUI(例如 X11)是唯一连接到实际键盘设备的;并将这些键转换为 GUI 中的 events。按下某个键时,GUI 中具有 输入焦点 的 window 将接收事件。
终端仿真器 是一个在 GUI 中运行的程序,为程序提供 1970 年代的 GUI 界面。该程序使用一种特殊类型的 tty-device,称为 pseudo-tty,其功能非常类似于支持终端特定功能的 pipe(2) (tc* , 读写控制)。当 终端仿真器 接收到指示击键的 GUI 事件时,它会将其注入 pseudo-tty,然后将其作为 ascii/utf-8 字符提供给程序。
GUI 通过配置选择哪个 window 具有输入事件的焦点。有些人更喜欢地理 - window 鼠标指针所在的位置接收这些事件;有些人更喜欢 单击以聚焦,您必须在其中单击 window 以确定谁获得焦点。两者各有优缺点;但是如果你经常在 irc/slack/... 中收到来自某人的奇怪消息,他们可能会选择 click-to-focus.
在没有图形用户界面的情况下,答案既简单又复杂。在明显的情况下,它是程序向您打印“$”提示符;在复杂的情况下,您需要阅读 会话、进程组、控制终端、作业控制 。
下面是一个简单的 c 程序(适用于 Ubuntu OS),它等待任何键盘键被按下然后终止。
#include <cstdio>
#include <conio.h>
int main() {
while(true) {
if (_kbhit()) {
printf("Key hit\n");
return 0;
}
}
return 0;
}
如果我在终端 nr 上启动这个程序。 1,仅当鼠标指向终端 1 时,程序才会对我按下按键做出反应。因此,如果两个这样的程序同时 运行 作为单独的进程,按下一个键将最多终止一个程序.
OS如何知道向哪个进程发送键盘中断?
首先,这是一个直接从键盘缓冲区读取输入的程序(a.k.a。键盘记录器):
#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
另一方面,您的代码使用 conio.h
库读取键盘事件,它在内部调用 getchar()
从 stdin:
When a command is executed via an interactive shell, the streams (i.e. stdin) are typically connected to the text terminal on which the shell is running,
一个进程的标准输入将指向与另一个进程的标准输入不同的文件。
现在 OS(即键盘驱动程序)所做的是将按键从键盘缓冲区转发到前台进程的标准输入。由于在您的情况下,只有一个程序 运行 作为前台进程,因此 key-press 将仅转发到标准输入流之一。
大问题。在您的示例中,正如 所述,它 没有;取决于您对 OS.
的定义在经典的unix系统中,GUI是由用户space中相对常规的程序运行提供的。 GUI(例如 X11)是唯一连接到实际键盘设备的;并将这些键转换为 GUI 中的 events。按下某个键时,GUI 中具有 输入焦点 的 window 将接收事件。
终端仿真器 是一个在 GUI 中运行的程序,为程序提供 1970 年代的 GUI 界面。该程序使用一种特殊类型的 tty-device,称为 pseudo-tty,其功能非常类似于支持终端特定功能的 pipe(2) (tc* , 读写控制)。当 终端仿真器 接收到指示击键的 GUI 事件时,它会将其注入 pseudo-tty,然后将其作为 ascii/utf-8 字符提供给程序。
GUI 通过配置选择哪个 window 具有输入事件的焦点。有些人更喜欢地理 - window 鼠标指针所在的位置接收这些事件;有些人更喜欢 单击以聚焦,您必须在其中单击 window 以确定谁获得焦点。两者各有优缺点;但是如果你经常在 irc/slack/... 中收到来自某人的奇怪消息,他们可能会选择 click-to-focus.
在没有图形用户界面的情况下,答案既简单又复杂。在明显的情况下,它是程序向您打印“$”提示符;在复杂的情况下,您需要阅读 会话、进程组、控制终端、作业控制 。