使用epoll与设备(/ dev / event / ...)有效吗? [英] Is it efficient to use epoll with devices (/dev/event/...)?

查看:186
本文介绍了使用epoll与设备(/ dev / event / ...)有效吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个创建代理虚拟设备(更准确地说是一个虚拟的Xbox 360 pad)的程序小程序。我设法使用 uinput 界面创建它,我正确设置它,它的工作原理很好。 p>

为了将命令提供给这个虚拟设备,我从另一个实际接口读取事件(在这种情况下, em> PS3 pad),我打开具有这些标志的真实设备文件:

  fd = open(/ dev / input / event22,O_RDONLY); //打开PS3垫

主循环类似于(减去错误检查):

  while(run){
input_event ev = {0};
read(fd,& ev,sizeof(struct input_event));
//从PS3转换 - > Xbox 360
convert(ev);
//写入新的虚拟键盘
write(fd_virtual,& ev,sizeof(struct input_event));
}

您可以想象, read(fd,& amp ; ev,sizeof(struct input_event)); 是一个阻塞调用,我想有一种超时循环遍历循环,并检查其他事件/执行其他代码。



由于这些原因,我正在考虑将 read(fd ... call in a epoll 循环,所以我也可以超时。



问题是,是否会有效地这样做吗?
凭借使用 epoll_wait ,我引入了更多的延迟当前的循环,因此延迟了虚拟垫的响应性

解决方案


由于使用epoll_wait,我在当前循环中引入了额外的延迟,从而延迟了虚拟键盘的响应速度?


是的,你su


这样做是否有效?


我确定是的,但这在很大程度上取决于您对高效的定义。



我们在说什么是人类输入设备。我们关心的主要是在处理HID时是延迟,它不应该滞后,按键上的反应应该是即时的。人类的即时是什么?有一个很好的讨论,但我最喜欢的一个论点是,在高水平的田径比赛中,你会是取消资格,在信号后不到100 ms开始。



但是,100毫秒是一个时间预算,用于对输入信号进行整体处理,从按键到游戏中的一些可察觉的变化。 输入滞后的维基百科页面有一些关于这个预算通常花费的数字。



无论如何,我认为1毫秒是绝对安全的开销,你可以添加你的代理,没有人会注意到,让我们说,这是我们的最大延迟的目标(如定义高效)。



所以,让我们假设你对当前代码的响应时间感到满意。添加 epoll()调用时会发生什么变化?基本上,你正在为另一个系统调用添加一些时间,因为现在而不是一个系统调用来获取你所做的两个。因此,可能会比原始代码慢两倍(我们暂时忘记了不同系统调用的处理时间差异)。但是真的那么糟糕吗?



为了回答这个问题,我们需要对系统调用开销进行一些估计。如果我们懒得自己测量,我们可以使用一些数字从20年前,一些关于系统调用的人员的数字,一些微内核的IPC号码(他们总是关心),一些 StackOverflow中的随机数字请问Rich ,并将微秒级别安置在一个安全的假设之下。



所以问题归结为是否在你的毫秒(如1000微秒)的时间预算中添加一些(我们甚至说10)微秒是显着的。我认为这不是。



只有一点可能的问题,当你要从只需添加 epoll()


循环遍历循环并检查其他事件/执行其他代码。


您需要小心留意您的时间预算,以进行这些循环和检查。但是在这里再一次1毫秒可能已经足够了。


I am working on a monothreaded process applet which creates a proxy virtual device (more precisely a virtual Xbox 360 pad); I do manage to create it with the uinput interface, I set it up properly and it works just fine.

In order to feed commands to this virtual device, I read events from another real interface (in this case a PS3 pad), and I open the real device file with these flags:

fd = open("/dev/input/event22", O_RDONLY); // open the PS3 pad

The main loop is something like (minus error checking):

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));
}

As you can imagine the read(fd, &ev, sizeof(struct input_event)); is a blocking call and I would like to have a sort of timeout to cycle through the loop and check for other events/execute other code.

For these reasons I am thinking of encapsulating that read(fd... call inside an epoll loop, so I can also have a timeout.

Question is, would it be efficient to have it done this way? By virtue of using epoll_wait, am I introducing additional delays to the current loop, thus delays in responsiveness of the virtual pad?

解决方案

By virtue of using epoll_wait, am I introducing additional delays to the current loop, thus delays in responsiveness of the virtual pad?

Yes, you sure do.

would it be efficient to have it done this way?

I'm sure yes, but that very much depends on your definition of "efficient".

What we're talking about here is a human input device. What we care mostly when dealing with HIDs is latency, it shouldn't lag, the reaction on the keypress should be instant. What is "instant" for a human being? There is a nice discussion there, but one argument that I like most is that on a high-level athletics competition you'd be disqualified for starting in less than 100 ms after the signal.

But that 100 ms is a time budget to make whole processing of the input signal, from key press to some perceivable changes in the game. Wikipedia page on input lag has some numbers on how this budget is usually spent.

Anyway, I think 1 ms is absolutely safe overhead you can add with your proxy and no one will notice, let's say that's our goal for maximum latency (as in definition of "efficient").

So, let's assume that you're satisfied with the response time from your current code. What changes when you add an epoll() call? Basically, you're adding some time for another syscall to be made, because now instead of one syscall to get the value you're making two. So potentially it's about two times slower than your original code (let's forget about difference in processing time for different syscalls for the moment). But is it really that bad?

To answer that question we need to have some estimate of what a syscall overhead is. If we're too lazy to measure it ourselves, we can use some numbers from 20 years ago, some numbers from people that care about syscalls, some IPC numbers from microkernel guys (they always care), some random numbers from StackOverflow or just ask Rich and settle around something microsecond-level as a safe assumption.

So the question boils down to whether adding some (let's even say 10) microseconds is noticable within your millisecond (as in 1000 µs) time budget. I think it's not.

There is just one little possible problem, when you're to go from "just adding epoll()" to

cycle through the loop and check for other events/execute other code.

You need to be careful to stay within your time budget for these loops and checks. But then again 1 ms is probably more than enough for you here.

这篇关于使用epoll与设备(/ dev / event / ...)有效吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆