1. 问题:
linux平台下,按键应用处于忙状态,此时频繁按下按键,出现按键事件丢失等异常现象?
2. 原因:
按键缓冲区是一个环状缓冲区,如果插入事件导致head与tail相等,即可判定缓冲区发生了溢出,会丢弃缓冲区中的所有事件,同时内核会向缓冲区放入一个SYN_DROPPED事件,通知用户程序事件有丢失。
3. 解决:
由于内核input子系统上报的是按下和抬起事件,内核清空缓冲队列后可能会出现只上报单个抬起或者按下事件要注意处理。本次发现问题就是因为系统只上报按下事件没有抬起事件导致应用触发了长按事件。
当收到SYN_DROPPED事件时:
- 清除按键保存的状态
- 忽略掉第一次就出现的抬起事件
- 忽略掉重复的按键事件(按键事件正常应该是按下、抬起成对出现的)
4. 内核代码
kernel/drivers/input/evdev.c
static void __pass_event(struct evdev_client *client,
const struct input_event *event)
{
...