进一步阅读

进一步阅读

我试图更好地理解(概念上)像 X 这样的系统是如何工作的。我的理解是,对于 X 接收键盘事件,它有一个内部事件循环,该循环执行阻塞读取/dev/input/event0,例如,内核将其公开为读取用户输入的一种方式。然后,它获取该事件,进行一些处理(在用户空间中)并使用某种形式的事件队列将其传递给活动窗口。如果我对这本质上是如何工作的有误解,请纠正我。

但这就是我感到困惑的地方。如果/dev/input/event0eventXX正在被 X 直接读取,因此这些事件正在被消耗,那么如何让其他进程执行读取操作eventXX?我们可以让 Python 进程从设备读取数据,也可以从命令行读取数据等等。

我的理解(这可能是我错的地方)是字符设备的输出被单个进程消耗,因此如果有两个进程正在read调用,/dev/...那么只有一个read调用会返回给定的数据。那么,如果 X 从字符设备获取所有数据,其他进程如何能够读取相同的键盘数据呢?

答案1

Xorg 和其他程序协商共享 I/O 设备。它们以两种模式运行。当活动时,它们会轮询输入设备,kevent(…EV_ENABLE…)或针对其文件描述符使用类似的设备,并写入显示设备。当不活动时,它们不会轮询输入设备,kevent(…EV_DISABLE…)或者针对其文件描述符使用类似的设备,并且不会写入显示设备。

在任何给定时间只有一个程序访问 I/O 设备。这是因为,正如您所观察到的,如果多个程序这样做,显示就会损坏,并且不确定各个输入事件的结束位置。 (Linux中内置的终端仿真器在这里算作一个程序,虽然它不是一个过程。它不使用轮询,而是在输入设备驱动程序中具有内部挂钩,并控制输入流的打开和关闭,并有一个标志告诉它何时应该将更新的字符单元实现到显示设备,从而达到相同的效果.)

他们使用一个内核虚拟终端作为谈判的手段。这就是 Xorg 服务器分配 KVT 的原因。使用特定于 KVT 设备的协议,其中涉及ioctl()只有该类型的设备能够理解并向进程发送信号,每个设备都可以协商何时负责显示器和人类输入设备 (HID) 以及何时内核内置终端仿真程序或其他一些程序(包括另一个 X 服务器)。

systemdlogind程序中对这一想法进行了重新发明,旨在允许 KVT 子系统未使用的 I/O 设备的协作程序之间进行相同的协商,例如完全独立的辅助显示器等,或者当没有首先它不是 Linux 中的 KVT 子系统。同样的原则也适用。程序在非活动状态时不使用文件描述符。

进一步阅读

答案2

多个读者都获得输入子系统事件的副本,至少在我的系统(Linux 5.10)上,键盘和鼠标事件。至少所有与 glob 匹配的设备:

/dev/input/by-path/*-event-{kbd,mouse}

尽管Xorgsystemd-login并且acpid所有人都将它们打开(如 所示lsof),但对我来说以这种方式工作。

evtest(1)只要未给出,您就可以使用 long 进行测试读取--grab(显然 X 不会“抓住”它),例如我键盘上的“shift”按键/释放”

 $ sudo evtest /dev/input/by-path/platform-i8042-serio-0-event-kbd |& grep ^Event:
Event: time 1642971418.691004, type 4 (EV_MSC), code 4 (MSC_SCAN), value 36
Event: time 1642971418.691004, type 1 (EV_KEY), code 54 (KEY_RIGHTSHIFT), value 1
Event: time 1642971418.691004, -------------- SYN_REPORT ------------
Event: time 1642971418.729131, type 4 (EV_MSC), code 4 (MSC_SCAN), value 36
Event: time 1642971418.729131, type 1 (EV_KEY), code 54 (KEY_RIGHTSHIFT), value 0
Event: time 1642971418.729131, -------------- SYN_REPORT ------------

(类型 4 是原始扫描码,与逻辑键盘事件类型 1 一起出现)。单次读取返回struct input_event(x86_64 上为 24 字节)的倍数,其中类型 0、代码 0 ( EV_SYN, SYN_REPORT) 数据包分隔相关输入数据包组。这与具有多维输入的触摸板和鼠标更相关。

(根据包元数据,evemu-tools这些天应该用于测试而不是evtest,但我没有尝试。)

请注意,我成功地使用事件设备来监视键盘空闲时间,并且脚本正确读取在 X 中或从控制台输入的事件,而其他读者继续获取所有这些按键的副本。

有关更多详细信息,请参阅以下文件:

  • /usr/include/linux/input.h
  • /usr/include/linux/input-event-codes.h
  • /usr/src/linux/Documentation/input/input.rst

相关内容