Hotdry.
systems-engineering

Linux 输入栈端到端追踪:从 evdev 硬件事件到 X11/Wayland 用户交付

详解 Linux 输入从内核 evdev 事件经子系统到 X11/Wayland 的协议细节与工程参数。

Linux 输入栈从硬件事件到用户空间交付的端到端流程高度模块化,确保高效处理键盘、鼠标和触控板等输入。核心观点:内核通过 evdev 标准化事件,用户空间 libinput 优化处理,最终由 X11 或 Wayland compositor 分发到应用。这种设计解耦硬件细节,支持多设备场景,但需关注 SYN_DROPPED 丢失和权限管理。

1. 内核输入管道:HID 到 input core 和 evdev

输入从硬件(如 USB HID)经总线驱动(如 usbhid)进入内核 input core(drivers/input/input.c)。input core 抽象 struct input_dev,注册设备并分发事件至 handler(如 evdev)。

关键协议:struct input_event { struct timeval time; __u16 type; // EV_KEY=1, EV_REL=2, EV_ABS=3 等 __u16 code; // KEY_A=30, REL_X=0 等 __s32 value; // 按下 = 1/2, 移动量 },每帧以 EV_SYN SYN_REPORT (0) 结束。

证据:venam.net 文章指出,“input core 通过 input_event 转发事件至 evdev,暴露 /dev/input/eventX”。HID 报告描述符解析后,hid-input 桥接至 input core,支持多设备(如键盘多接口)。

工程参数:

  • 能力位图:sysfs /sys/class/input/inputN/capabilities/{ev,key,rel,abs} 检查支持事件。
  • 拓扑:udevadm info -a /dev/input/event0 查看 PCI→USB→HID→input 链路。
  • 阈值:SYN_DROPPED 时内核丢事件,libevdev 需处理 delta 同步。

清单:

  • dmesg | grep input 确认驱动加载。
  • cat /proc/bus/input/devices 查看 Handlers=eventX。
  • modprobe uinput 测试虚拟设备。

2. evdev 接口与用户空间桥接

evdev(EVDEV_MINOR_BASE=64)标准化 /dev/input/event* 为状态 ful 流,仅报告变化。libevdev 封装 ioctl(如 EVIOCGKEYCODE),处理 SYN_DROPPED(libevdev_next_event 返回 LIBEVDEV_STATE_SYN_DROPPED)。

证据:libevdev 文档,“libevdev 是 read (2) 的增强版,位于 kernel 与进程间”。Wayland 架构页确认,“内核 evdev 发送事件至 compositor”。

参数:

  • 非阻塞:open (O_RDONLY|O_NONBLOCK),drain 旧事件。
  • Grab:ioctl (EVIOCGRAB,1) 独占设备。
  • 风险:缓冲溢出阈值 16 事件,超时 poll (2) 500ms。

清单:

  • evtest /dev/input/event0 测试事件。
  • libevdev-events 示例监控。

3. libinput 用户空间栈:优化与座席管理

libinput 基于 libudev 枚举设备(ID_INPUT_* 属性),分组(LIBINPUT_DEVICE_GROUP),经 logind/seatd 获取 fd(seat0)。处理去抖(debounce 25ms)、加速(adaptive 配置文件)、手掌检测(压力阈值)。

证据:venam 总结,“libinput 统一指针 / 键盘 / 触控,处理 MT 槽位与跟踪 ID”。Wayland 示例栈:kernel→libevdev→libinput→Compositor。

参数:

  • 座席:loginctl seat-status,ID_SEAT=seat0。
  • 配置:/etc/X11/xorg.conf.d/ 匹配 MatchIsTouchpad "on",Option "Tapping" "on"。
  • 阈值:触控 FingerLow=25/High=30,DWT 禁用打字时触控。

清单:

  • libinput list-devices 列设备组。
  • libinput debug-events 实时追踪。
  • hwdb quirks:systemd-hwdb update 修复分辨率。

4. 到 X11/Wayland 交付:协议与分发

X11:xf86-input-libinput 驱动,XInput2 事件(XI_Motion 等)。xinput list-props 配置,XTEST 虚拟输入。

Wayland:compositor(如 wlroots)直连 libinput,wl_pointer/wl_keyboard 事件至焦点客户端。libei EIS 仿真输入。

证据:Wayland 文档,“compositor 决定窗口,逆变换坐标,直接分发”。venam,“X11 中间人多,Wayland 去除”。

参数:

  • X11:xinput set-prop "Touchpad" "libinput Accel Speed" -0.5。
  • Wayland:环境 XKB_DEFAULT_LAYOUT=us,gsettings org.gnome.desktop.peripherals。
  • 监控:xev (X11),wev (Wayland)。

回滚:udev 规则权限 0660 input,TAG+="uaccess"。

资料来源:venam.net “The Input Stack on Linux”(内核 evdev 拓扑);libevdev 文档(SYN_DROPPED 处理)。“libevdev 是 read (2) 的增强版”。

查看归档