C

时间:2016-03-12 18:32:00

标签: multithreading epoll epollet

我想使用epoll和EPOLLET编写一个多线程TCP侦听器。

我看到有几种可能性:

  1. 每个线程都有自己的epoll fd,bind()使用SO_REUSEPORT(但只有Linux内核3.9)并处理自己的连接。在这种情况下不需要EPOLLONESHOT,因为每个线程都处理自己的文件描述符。

  2. 有一个接受连接的主线程和几个处理这些连接的工作线程。每个工作线程都有自己的epoll fd。在这种情况下,主线程如何公平地分配工作线程之间的连接?它可以使用循环方式将文件描述符添加到另一个线程的epoll fd(但可能会发生该特定线程仍忙于处理另一个连接)。或者可以将连接添加到全局队列,主线程将使用pthread_cond_signal(),但是我们需要一个互斥锁和一个条件变量。

  3. 有一个接受连接的主线程和几个处理这些连接的工作线程。有一个全局epoll fd,在这种情况下需要EPOLLONESHOT,所以不是所有的线程都被唤醒了同一个事件。

  4. 我知道,如果使用EPOLLET,一旦我收到有关某个事件的通知,我就必须消耗fd,直到我得到EAGAIN

    如果不支持套接字选项SO_REUSEPORT(旧内核),哪个选项最好?

2 个答案:

答案 0 :(得分:1)

  1. 1的变体但没有SO_REUSEPORT就是拥有一个共享的侦听套接字。每个工作线程都运行自己的事件循环,除了处理自己的连接外,它们还在侦听套接字上执行非阻塞的accept()。有关更全面的说明,请参阅例如http://aosabook.org/en/nginx.html

答案 1 :(得分:0)

  1. 不使用SO_REUSEPORT的解决方案是在所有线程之间共享一个共同的epoll fd和一个公共侦听器。 EPOLLONESHOT是必需的,因此一次只有一个线程处理某个fd的事件。