Как прочитать несколько дескрипторов файлов, используя epoll_select с epollet?
Вопрос
Человек Epoll:
The suggested way to use epoll as an edge-triggered (EPOLLET) interface is as follows:
i with nonblocking file descriptors; and
ii by waiting for an event only after read(2) or write(2) return EAGAIN.
Представьте, что у нас есть два FDS: первый пассивный, данные доступны только иногда, второй активен, данные только иногда не доступны.
Epoll_wait вернул, что мы можем прочитать оба. Мы читаем {первое, чем второе} в цикле (без вызовов в epoll_wait из-за него может внезапно блокировать, пока данные все еще доступны).
Теперь первый файловый дескриптор вернул EAGAIN на чтение.
Что делать?
- Если мы продолжим чтение второй FD в цикле (без вызовов в epoll_wait), мы можем пропустить, что данные стали доступными на первом FD. Он просто прочитал и читает и читает без оркестра.
- Если мы будем «проконсультироваться» с EPOLL_WAIT перед каждым чтением со второго FD, epoll_wait может внезапно блокировать из-за того, что ничего не изменилось с предыдущего вызова (данные, все еще не доступные на первом FD и все еще доступны на втором FD).
Как продолжить обработку второго FD, но не забывая о первой FD?
Обновлять: Найдено еще одна вещь: Man Epoll_Wait:
while specifying timeout equal to zero makes epoll_wait() to return immediately even if no events are available
С этим я могу перечислить события для FDS, даже если нет событий.
Решение
Если FD2 постоянно читается, вы можете учитывать, что EPOLL не подходит для него. Возможно, стоит вращаться с нити, чтобы просто сидеть и прочитать его.
В противном случае прочитайте FD2 в цикле, пока он не будет сливаться, а в цикле не пытается прочитать FD1 один раз каждый x раз. Если FD1 имеет данные, прочитайте его. Если нет, вы просто получите EAGAIN, сбросьте счетчик X и вернитесь к чтению FD2. Когда оба сливаются, вы вернулись в epoll_wait.
Что-то типа:
count = 1;
while (true)
{
read fd2;
if (EAGAIN)
break;
else
process data;
count--;
if (! count)
{
while (true)
{
read fd1;
if (EAGAIN)
count = 10;
break;
else
process data;
}
}
}