如何重置使用 EFD_SEMAPHORE 创建的 Linux 事件描述符

How to reset a Linux event descriptor created with EFD_SEMAPHORE

提问人:Simon Walke 提问时间:8/9/2023 最后编辑:Simon Walke 更新时间:8/10/2023 访问量:66

问:

我有一个用 C 代码创建的事件描述符,如下所示:

int notifyED = eventfd(0, EFD_SEMAPHORE | EFD_CLOEXEC);

计数器按预期上升和下降,这是调用 和 的结果。eventfd_read()eventfd_write()

到目前为止一切都很好。现在,我想“刷新”此事件 FD 中的 64 位计数器,以便它重置为零。

  • 刷新操作需要对监视事件 FD 的任何轮询/电子轮询实例“透明”。

  • 刷新后,任何轮询实例都不应生成新的 POLIN,直到进一步发生。eventfd_write()

显然,类似信号量的语义会阻止计数器在单个 read() 操作中被重置,所以我以这种方式实现了刷新:

int flushED = eventfd(0, EFD_SEMAPHORE);

notifyED = dup3(flushED, notifyED, O_CLOEXEC);
close(flushED);

如果我正确理解了文档页面及其变体,则应以原子方式关闭并重新分配事件描述符。注意:程序总是在退出之前显式调用。dup()dup3()close(notifyED)

编辑:更新为用于维护 CLOEXEC 标志,并在有关关闭两个描述符的注释中加入反馈。dup3()

我已经知道的替代解决方案:

  1. 具体到 epoll,请使用 ctl_add() 和 ctl_del() 将描述符替换为新描述符;

  2. 重复调用,直到计数器为零。eventfd_read()

具体问题:

  1. 这种方法可以接受吗?dup3()

  2. 我是否泄露了描述符资源?

  3. 根据我的测试,epoll 实例似乎按预期运行。我错过了什么陷阱?

Linux 轮询 epoll dup2

评论

0赞 Martin Rosenau 8/10/2023
您是否知道在调用时必须关闭两个文件句柄?dup2()
0赞 Simon Walke 8/10/2023
谢谢@MartinRosenau:不,我不知道,因此我提出了关于资源泄漏的具体问题。也许我应该先将单个调用分离到 tempED = eventfd(0,EFD_SEMAPHORE) 中,然后将该临时描述符显式传递到 dup2() 和 close(tempED) 中?

答: 暂无答案