【问题标题】:How should I use epoll to read and write from the same FD我应该如何使用epoll从同一个FD读取和写入
【发布时间】:2020-04-18 10:33:29
【问题描述】:

环境

  • Linux x64
  • Ubuntu 16.4
  • C++

用例

  • 异步 IO (epoll)
  • 一个套接字用于读取和写入
  • 读写操作不同步,在套接字上迭代完成

示例流程

  1. 设置套接字(EPOLL_CTL_ADD
  2. 开始读取 (EPOLL_CTL_MOD + EPOLLIN | EPOLLONESHOT)
  3. 等待读取数据时
    • [a] 写入一些数据(EPOLL_CTL_MOD + EPOLLOUT | EPOLLONESHOT

问题描述

  • 在上面的 #2 中注册了 EPOLLIN 读取操作
  • 在 #3.a 中,EPOLLOUT 写入完成已注册在从套接字读取任何数据之前
  • 鉴于上述情况,写完成操作@3.a 会取消挂起的读操作吗?
    • 换句话说,假设 FD 最初是用没有设置 EPOLLIN 的 (EPOLL_CTL_MOD + EPOLLOUT) 调用的,将调用 EPOLL_CTL_MOD + EPOLLOUT erase 先前注册的 EPOLLIN 给定数据尚未准备好被读取??

上述情况的可能解决方法

  • 是通过epoll_wait线程路由所有读/写操作来本地管理req IO状态,因此,而不是从任意线程调用EPOLL_CTL_MOD,确保它将始终从执行 epoll_wait 的同一线程中调用,在该线程中可以安全地维护 FD IO 状态 (EPOLLOUT/EPOLLIN)。
  • 此解决方法的问题在于,它要求通过 epoll_wait 线程同步所有 IO 启动,这会导致额外的上下文切换,这可能会对性能产生不利影响...

这就是我想要弄清楚的:

有没有什么方法可以同步普通 FD 上的读/写 IO 操作而无需通过 epoll_wait 线程进行同步?有没有办法直接调用 EPOLL_CTL_MOD 而无需重置先前的状态?是否有任何线程安全的方式在已设置 EPOLLIN 的 FD 上添加 EPOLLOUT

【问题讨论】:

  • 如果你可以读写两个不同的fd,你就可以用完全相同的过程读写同一个fd。只需使用 EPOLLIN|EPOLLOUT 设置一次套接字。
  • 这是真的,但是,我需要处理 w 情况,例如。套接字(EPOLLIN)上有待处理的读取有效负载,并且没有提供要读取的缓冲区......并且要求我以线程安全的方式管理 FD 状态,因为它将被多个线程访问...... .如果可能的话,我想避免这种复杂性......打电话给例如。 EPOLL_CTL_MOD + POLLEIN 可以结合 w/ 提供缓冲区,POLLEOUT 也是如此......现在,当读取有效负载可用时,EPOLL_CTL_MOD 被称为 w POLLEIN | POLLEIN,但是,调用应用真的只对写入数据感兴趣......
  • 有趣,我认为与EPOLL_CTL_DISABLE 相关,尽管它侧重于删除资源(以线程安全的方式)
  • 你也可以dup()socket FD,这样你就有2个不同的FD,每个都有自己的事件掩码。
  • 是的,当然值得一试,我想知道我是否会在特定 FD 或两个副本上收到 epoll_wait 通知...我们会看到...

标签: c++ linux multithreading asynchronous epoll


【解决方案1】:

SOoo ...,正如@Hasturkun 所建议的那样,使用dup 过滤EPOLLIN 和EPOLLOUT 事件(以线程安全的方式)起到了作用,但是,对我来说,这看起来更像是一种破解/解决方法...... . 我觉得没有更优雅的解决方案很尴尬... windows IOCompletion 端口对我来说似乎更优雅...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    • 2015-12-24
    • 1970-01-01
    • 2020-12-06
    • 2016-01-28
    • 2020-02-20
    相关资源
    最近更新 更多