Многопоточный TCP слушатель с epoll и EPOLLET в C
Я хочу написать многопоточный TCP-слушатель, используя epoll и EPOLLET
,
Я видел, что есть несколько возможностей:
Каждый поток имеет свой собственный epoll fd, делает
bind()
с помощьюSO_REUSEPORT
(но только до ядра Linux 3.9) и обрабатывает свои собственные соединения.EPOLLONESHOT
в этом случае не понадобится, поскольку каждый поток обрабатывает свои собственные файловые дескрипторы.Существует основной поток, который принимает соединения, и несколько рабочих потоков, которые обрабатывают эти соединения. Каждый рабочий поток имеет свой собственный epoll fd. Как основной поток в этом случае может справедливо распределить соединения между рабочими потоками? Он может добавить файловый дескриптор к epoll fd другого потока с использованием метода циклического перебора (но может случиться, что этот конкретный поток все еще занят обработкой другого соединения). Или соединения могут быть добавлены в глобальную очередь, и основной поток будет использовать
pthread_cond_signal()
, но тогда нам нужен мьютекс и условная переменная.Существует основной поток, который принимает соединения, и несколько рабочих потоков, которые обрабатывают эти соединения. Существует глобальный epoll fd,
EPOLLONESHOT
тогда потребуется в этом случае, поэтому не все потоки просыпаются для одного и того же события.
Я знаю, что если EPOLLET
используется, как только я получаю уведомление о событии, я должен истощить fd, пока не получу EAGAIN
,
Если опция сокета SO_REUSEPORT
не поддерживается (старое ядро), какой вариант будет лучшим?
2 ответа
- Решение без использования
SO_REUSEPORT
будет иметь общий epoll fd и общий прослушиватель, которые являются общими для всех потоков.EPOLLONESHOT
требуется, поэтому только один поток обрабатывает события для определенного fd одновременно.
- Вариант 1. но без SO_REUSEPORT - иметь общий сокет прослушивания. Каждый рабочий поток запускает свой собственный цикл обработки событий, и в дополнение к обработке своих собственных соединений они также выполняют неблокирующую функцию accept() в сокете прослушивания. Более подробное описание см., Например, http://aosabook.org/en/nginx.html