libevdev事件时间戳为何回绕?如何计算按键按压释放间隔?
python-libevdev事件时间戳回绕问题
我在使用python-libevdev时发现事件时间戳存在回绕现象,运行如下脚本:
import libevdev as ev with open('/dev/input/by-path/my-event-kbd', 'rb') as fd: device = ev.Device(fd) device.grab() for e in device.events(): if e.matches(ev.EV_KEY): if e.value == 0: print('release', e.usec) elif e.value == 1: print('press ', e.usec)
得到输出:
press 285047 release 898527 press 383116 release 828000 press 164149 release 295935 press 929637 release 65158 press 593924 release 750227 press 81770 release 210363 press 533884 release 652184 press 949230 release 81242
InputEvent.usec的文档仅说明其为“微秒级时间戳”,请问:
- 该时间戳回绕现象的原因是什么?
- 如何利用这些值计算按键按压与释放的时间间隔?
时间戳回绕的原因
你看到的回绕现象,本质是因为usec字段只对应Linux输入子系统input_event结构体里的tv_usec部分——这个字段仅存储1秒以内的微秒数(范围0-999999),完整的时间戳还包含tv_sec(秒数)字段。python-libevdev的InputEvent对象同时提供了sec属性(对应tv_sec),但你只打印了usec。
当事件跨越秒数边界时,比如按压事件发生在第N秒的929637微秒,释放事件发生在第N+1秒的65158微秒,此时usec就会从接近100万的数值跳回到几万,看起来像是“回绕”,但实际是秒数已经递增了,只是你没用到这个字段。
计算按键按压与释放的时间间隔
要计算正确的时间间隔,必须结合sec和usec得到完整的微秒级时间戳,再用释放事件的完整时间减去按压事件的完整时间。
修改后的脚本示例:
import libevdev as ev # 存储每个按键的按压时间(键码: 完整微秒时间戳) press_times = {} with open('/dev/input/by-path/my-event-kbd', 'rb') as fd: device = ev.Device(fd) device.grab() for e in device.events(): if e.matches(ev.EV_KEY): # 计算完整时间戳:秒数转微秒 + 微秒部分 full_usec = e.sec * 1_000_000 + e.usec if e.value == 1: # 按压事件 press_times[e.code] = full_usec print(f'press {e.code}: {full_usec}') elif e.value == 0: # 释放事件 if e.code in press_times: duration = full_usec - press_times[e.code] print(f'release {e.code}: {full_usec}, 按压时长: {duration} 微秒') del press_times[e.code]
这个脚本会记录每个按键的完整按压时间,释放时计算并输出按压时长,完全避免了时间戳回绕的问题。
内容的提问来源于stack exchange,提问作者jth
相关产品推荐
相关产品推荐

