【问题标题】:multithreaded epoll多线程 epoll
【发布时间】:2013-01-13 03:17:36
【问题描述】:

我正在使用 epoll(边缘触发)和非阻塞套接字创建一个多线程服务器。目前我正在主线程上创建一个事件循环并等待通知,它可以正常工作
我必须在两种方法之间进行选择以使其成为多线程:

  1. 为每个线程创建一个事件循环并添加服务器套接字的文件描述符以查找每个线程上的通知。 (这可能吗?我的意思是:epoll 线程安全吗?)
  2. 创建单个事件循环并等待通知。每当收到通知时,都会产生一个线程来处理它。

如果我使用第一种方法,是否有机会让多个线程收到相同事件的通知?我该如何处理这种情况?

最好的方法是什么? 谢谢。

【问题讨论】:

  • Is epoll thread-safe?的可能重复
  • 是的,epoll 是线程安全的。是的,你可以做到。只需四处搜索详细信息,SO 和 Google 都充满了这些信息。
  • 谢谢。我也想知道是否可以将相同的文件描述符添加到多个 epoll 循环中。我可以吗?

标签: c linux multithreading sockets epoll


【解决方案1】:

epoll 是线程安全的

希望下面的代码可以帮助你

https://github.com/jingchunzhang/56vfs/blob/master/network/vfs_so_r.c

【讨论】:

    【解决方案2】:

    我也在使用epoll 编写服务器,并且我考虑了与您连接的相同模型。

    使用选项1是可以的,但是可能会造成“雷声从众”的效果,可以阅读nginx的源码找到解决方法。至于选项2,我认为最好使用线程池而不是每次都产生一个新线程。

    您还可以使用以下型号:

    主线程/进程:accept 使用阻塞 IO 的传入连接,并使用 BlockingList 将 fd 发送到其他线程或使用 PIPE 发送到其他进程。

    子线程/进程:分别创建epoll的实例,并将传入的fd添加到epoll,然后用非阻塞IO处理。

    【讨论】:

      【解决方案3】:

      每个线程的事件循环是最灵活的和高性能的 您应该为每个事件循环创建一个 epoll fd,无需担心 epoll 线程安全问题。

      【讨论】:

        【解决方案4】:

        epoll 是线程安全的,一个好的解决方案是你的主进程停留在 accept(2) 中,一旦你在目标线程的 epoll fd 中注册了文件描述符,这意味着你有一个 epoll 队列每个线程,一旦创建线程,您将共享 epoll 文件描述符作为调用 pthread_create(3) 中的参数,因此当新连接到达时,您使用 epoll fd 为目标执行 epoll_ctl(...EPOLL_CTL_ADD..)线程和在accept(2)之后创建的新socket,有意义吗?

        【讨论】:

        • 为什么不直接将监听socket描述符添加到epoll集合中,当新的客户端连接请求到达时,accept连接,将新连接的socket描述符添加到epoll集合中,在主线程?当真实数据到达时,产生一个新线程来处理它。这样,程序看起来更精确。
        【解决方案5】:

        我认为选项 1 更受欢迎,因为非阻塞 IO 的主要目的是避免创建和销毁线程的开销。

        以流行的Web服务器nginx为例,它创建多个进程(不是线程)来处理一个句柄上的传入事件,并在子进程中处理事件。它们都共享同一个监听套接字。它与选项 1 非常相似。

        【讨论】: