我很好奇硬件如何与操作系统交互并发现了这篇文章:键盘输入和文本输出如何工作?
似乎很多魔法都发生在 /dev/input 目录中。我决定看看我自己的操作系统(Ubuntu 16.10),看看能找到什么。所有这些文件都列为 0 字节,当我这样做时,sudo cat mouse0 | hexdump -C
我会得到大量如下所示的十六进制数据:
00000000 b3 82 8a 58 00 00 00 00 53 74 09 00 00 00 00 00 |...X....St......|
00000010 01 00 1c 00 00 00 00 00 b3 82 8a 58 00 00 00 00 |...........X....|
00000020 53 74 09 00 00 00 00 00 00 00 00 00 00 00 00 00 |St..............|
00000030 b6 82 8a 58 00 00 00 00 06 56 0e 00 00 00 00 00 |...X.....V......|
00000040 01 00 10 00 01 00 00 00 b6 82 8a 58 00 00 00 00 |...........X....|
00000050 06 56 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 |.V..............|
所以我有几个问题:
该文件的目的是什么?在我看来,这些设备文件仅用作将扫描代码从内核传输到 X 服务器的中间人。为什么不直接从内核发送到 X 服务器呢?
为什么有这么多?我有 20 多个单独的事件文件,但只有一个键盘和鼠标。
答案1
我将以相反的顺序回答这个问题:
- 为什么有这么多?
这些设备代表机器上存在的大多数输入(还有其他设备,例如麦克风将不会在 中进行管理/dev/input
)。与 1 个键盘加 1 个鼠标会产生 2 个设备的假设相反,即使是最简单的键盘和最简单的鼠标仍然会产生 6 个设备。
为什么是 6?因为Xorg在启动时会创建一个测试输入键盘和一个测试输入鼠标(都是虚拟的)。此外,它将测试键盘与实际键盘聚合到主虚拟设备中。即它将执行输入的复用。测试鼠标和实际鼠标也会发生同样的情况。
另外,典型的计算机(台式机或笔记本电脑)除了键盘之外还有其他按钮:电源按钮、睡眠按钮。
那里的设备eventN
是用于 Xorg 创建的东西和计算机拥有的东西的设备。来自N
连续 ID,类似于 中的 ID xinput
。例如在我的机器上我有:
[~]# ls -l /dev/input/
total 0
drwxr-xr-x 2 root root 100 Jan 26 16:01 by-id
drwxr-xr-x 2 root root 140 Jan 26 16:01 by-path
crw-rw---- 1 root input 13, 64 Jan 26 16:01 event0
crw-rw---- 1 root input 13, 65 Jan 26 16:01 event1
crw-rw---- 1 root input 13, 74 Jan 26 16:01 event10
crw-rw---- 1 root input 13, 75 Jan 26 16:01 event11
crw-rw---- 1 root input 13, 76 Jan 26 16:01 event12
crw-rw---- 1 root input 13, 77 Jan 26 16:01 event13
crw-rw---- 1 root input 13, 66 Jan 26 16:01 event2
crw-rw---- 1 root input 13, 67 Jan 26 16:01 event3
crw-rw---- 1 root input 13, 68 Jan 26 16:01 event4
crw-rw---- 1 root input 13, 69 Jan 26 16:01 event5
crw-rw---- 1 root input 13, 70 Jan 26 16:01 event6
crw-rw---- 1 root input 13, 71 Jan 26 16:01 event7
crw-rw---- 1 root input 13, 72 Jan 26 16:01 event8
crw-rw---- 1 root input 13, 73 Jan 26 16:01 event9
crw-rw---- 1 root input 13, 63 Jan 26 16:01 mice
crw-rw---- 1 root input 13, 32 Jan 26 16:01 mouse0
crw-rw---- 1 root input 13, 33 Jan 26 16:01 mouse1
并xinput
给了我类似的 ID:
[~]$ xinput list
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ Logitech USB Optical Mouse id=10 [slave pointer (2)]
⎜ ↳ SynPS/2 Synaptics TouchPad id=14 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Video Bus id=7 [slave keyboard (3)]
↳ Power Button id=8 [slave keyboard (3)]
↳ Sleep Button id=9 [slave keyboard (3)]
↳ USB 2.0 Camera id=11 [slave keyboard (3)]
↳ Asus Laptop extra buttons id=12 [slave keyboard (3)]
↳ AT Translated Set 2 keyboard id=13 [slave keyboard (3)]
(看eventN
对应的id=N
)
没有 Xorg
1.1 该文件的用途是什么?
请注意,所有随机输入(包括我的 USB 摄像头!)都被 Xorg 视为虚拟键盘的一部分。这允许复用和解复用输入。例如,我可以通过 USB 鼠标或触控板移动鼠标,应用程序不需要知道其中的区别。
(事实上,USB 摄像头是虚拟键盘的一部分,因为它有一个按钮可以打开和关闭它。并且由于它是一个按钮,因此它成为键盘子系统的一部分。实际的视频输入在 中处理/sys/class/video4linux
。 )
换句话说,对于一个应用程序来说,实际上只有一个键盘和一个鼠标。但 Xorg 和内核都需要知道这些差异。这导致了最后一部分:
1.2 为什么不直接从内核发送到X服务器呢?
因为 Xorg 需要知道其中的区别。
在某些情况下它是有用的。您可以将 Xorg 中的按键以不同的方式重新映射到每个从属输入设备。例如,我有一个带有踏板的游戏装置,当在赛车游戏中使用时,它会输出a,b并且c为其每个踏板输出 。然而,在编程时,我将这些键重新映射到Esc、Ctrl和Alt,而不重新映射键盘本身上的键。
另外,机器没有必要运行 Xorg。例如,在无头服务器上我可以获得以下输出:
[~]$ ls -l /dev/input/
total 0
drwxr-xr-x 2 root root 80 Nov 8 02:36 by-path
crw-rw---- 1 root input 13, 64 Nov 8 02:36 event0
crw-rw---- 1 root input 13, 65 Nov 8 02:36 event1
crw-rw---- 1 root input 13, 66 Nov 8 02:36 event2
输入设备对应于串行端口(特别是在这种情况下)而不是键盘或鼠标。
答案2
不存在“直接发送”这样的事情。应用程序必须有某种读取数据的方法,在 Unix 中,这与读取常规文件的方式相同,即创建一个与常规文件 IO 系统调用配合使用的设备节点,以允许应用程序打开和读取它们。
除了鼠标和键盘之外,还有其他输入源。您可以通过查看来了解每一项的内容/sys/class/input
。在那里,您将使用相同的 inputNN 名称来细化文件,这些文件是指向 sysfs 中描述它们所代表的设备的另一个节点的符号链接。其他常见来源包括声卡(在插入和拔出插头时发出信号)和计算机上的物理电源按钮。