【问题标题】:Is it efficient to use epoll with devices (/dev/event/...)?将 epoll 与设备 (/dev/event/...) 一起使用是否有效?
【发布时间】:2017-06-14 16:32:23
【问题描述】:

我正在开发一个 单线程 进程小程序,它创建一个代理虚拟设备(更准确地说是一个虚拟 Xbox 360 键盘);我确实设法使用uinput 界面创建它,我正确设置它并且它工作得很好。

为了向这个虚拟设备提供命令,我从另一个真实界面(在本例中为PS3 pad)读取事件,我用这些标志打开 real device 文件:

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

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

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

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

出于这些原因,我正在考虑将 read(fd... 调用封装在 epoll 循环中,这样我也可以有一个超时。

问题是,这样做是否有效? 通过使用epoll_wait,我是否会在当前循环中引入额外的延迟,从而延迟虚拟键盘的响应?

【问题讨论】:

    标签: linux event-handling linux-device-driver epoll uinput


    【解决方案1】:

    通过使用 epoll_wait,我是否会在当前循环中引入额外的延迟,从而延迟虚拟垫的响应速度?

    是的,你肯定会的。

    这样做会不会有效率?

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

    我们在这里讨论的是人工输入设备。在处理 HID 时,我们最关心的是延迟,它不应该滞后,按键的反应应该是即时的。什么是人类的“即时”?有一个很好的discussion there,但我最喜欢的一个论点是,在高水平的田径比赛中,你会在信号发出后不到 100 毫秒内开始disqualified

    但是 100 毫秒是对输入信号进行整个处理的时间预算,从按键到游戏中的一些可感知的变化。 Wikipedia page on input lag 有一些关于通常如何使用此预算的数字。

    无论如何,我认为 1 毫秒是绝对安全的开销,您可以使用代理添加并且没有人会注意到,假设这是我们最大延迟的目标(如“高效”的定义)。

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

    要回答这个问题,我们需要对系统调用开销有一些估计。如果我们懒得自己测量它,我们可以使用一些numbers from 20 years ago、一些numbers from people that care about syscalls、一些IPC numbers from microkernel guys (they always care)、一些random numbers from StackOverflowjust ask Rich,并以微秒级作为安全假设。

    所以问题归结为在您的毫秒(如 1000 微秒)时间预算内增加一些(甚至说 10 微秒)是否值得注意。我认为不是。

    只有一个小问题,当您从“仅添加epoll()”变为

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

    您需要小心地控制这些循环和检查的时间预算。但话又说回来,1 毫秒对你来说可能已经足够了。

    【讨论】:

    • 您好,感谢您抽出宝贵时间回答,但不幸的是,这是非常通才的回答。我指的是游戏手柄,你可以想象它是关于游戏的。通常人们确实使用 100Hz,这意味着如果 epoll 调用可能会增加 x 更多毫秒(根据 Rich 的回答 - “最多毫秒级IO"),那么它确实有所作为,我正在寻找准确的答案。如果我必须自己测量它,我不妨这样做(但赏金的意义何在?)。
    • Rich 指的是 I/O 的大小可能不同,并且从设备传输到/从设备传输可能需要时间。您的 I/O 是您的 read()write(),只需将一些字节从已填充的缓冲区传输到虚拟设备的缓冲区,在您的特定情况下,我敢打赌您不会看到任何毫秒的读取和写入。而且我看不出epoll() 进入毫秒范围的任何方式(只是因为它的性质),这正是 --- 一些微秒。另外,从我的链接中仔细查看 FlexSC 论文,它们按周期计算事物,但这很容易转换为一些时间值。
    猜你喜欢
    • 1970-01-01
    • 2016-07-06
    • 2020-04-04
    • 2018-07-14
    • 1970-01-01
    • 1970-01-01
    • 2016-01-03
    • 2012-05-24
    • 2015-12-26
    相关资源
    最近更新 更多