Ema*_*ele 5 linux epoll event-handling linux-device-driver uinput
我正在开发一个单线程的进程applet,它创建一个代理虚拟设备(更确切地说是一个虚拟的Xbox 360 pad); 我设法使用uinput接口创建它,我正确设置它并且它工作得很好.
为了向这个虚拟设备提供命令,我从另一个真实接口(在这种情况下是PS3 pad)中读取事件,然后用这些标志打开真实的设备文件:
fd = open("/dev/input/event22", O_RDONLY); // open the PS3 pad
Run Code Online (Sandbox Code Playgroud)
主循环类似于(减去错误检查):
while(run) {
input_event ev = {0};
read(fd, &ev, sizeof(struct input_event));
// convert from PS3 --> Xbox 360
convert(ev);
// write to the new virtual pad
write(fd_virtual, &ev, sizeof(struct input_event));
}
Run Code Online (Sandbox Code Playgroud)
你可以想象这read(fd, &ev, sizeof(struct input_event));
是一个阻塞调用,我希望有一种超时循环循环并检查其他事件/执行其他代码.
由于这些原因,我想read(fd...
在epoll循环中封装该调用,所以我也可以暂停.
问题是,以这种方式完成它会有效吗?通过使用epoll_wait,我是否会对当前循环引入额外的延迟,从而延迟虚拟键盘的响应能力?
\n\n\n通过使用 epoll_wait,我是否会向当前循环引入额外的延迟,从而延迟虚拟板的响应能力?
\n
是的,你当然知道。
\n\n\n\n\n这样做会有效率吗?
\n
我确信是的,但这很大程度上取决于您对“高效”的定义。
\n\n我们这里讨论的是人类输入设备。在处理 HID 时,我们最关心的是延迟,它不应该滞后,按键反应应该是即时的。对于人类来说,什么是“即时”?那里有一个很好的讨论,但我最喜欢的一个论点是,在一场高水平的田径比赛中,如果你在信号发出后不到 100 毫秒内开始比赛,你将被取消资格。
\n\n但这 100 毫秒是对输入信号进行整个处理的时间预算,从按键到游戏中的一些可感知的变化。关于输入滞后的维基百科页面有一些关于通常如何花费预算的数字。
\n\n无论如何,我认为 1 毫秒是绝对安全的开销,您可以使用代理添加,没有人会注意到,假设这是我们最大延迟的目标(如“高效”的定义)。
\n\n因此,我们假设您对当前代码的响应时间感到满意。添加epoll()
通话后会发生什么变化?基本上,您要为另一次系统调用添加一些时间,因为现在您要进行两次系统调用,而不是一次系统调用来获取值。因此,它可能比原始代码慢大约两倍(让我们暂时忘记不同系统调用的处理时间差异)。但事情真的有那么糟糕吗?
为了回答这个问题,我们需要对系统调用开销进行一些估计。如果我们懒得自己测量,我们可以使用20 年前的一些数字、关心系统调用的人提供的一些数字、微内核人员(他们总是关心)的一些 IPC 数字、 StackOverflow 的一些随机数字或只是询问里奇并解决微秒级的问题作为安全的假设。
\n\n因此,问题归结为在您的毫秒(如 1000 \xc2\xb5s)时间预算内是否可以注意到添加一些(甚至可以说 10)微秒。我认为不是。
\n\nepoll()
当您从“仅添加”变为“仅添加”时,可能会出现一个小问题
\n\n\n循环执行循环并检查其他事件/执行其他代码。
\n
您需要小心地控制这些循环和检查的时间预算。但话又说回来,1 毫秒对你来说可能已经足够了。
\n