Как прочитать несколько файловых дескрипторов, используя epoll_select с EPOLLET? - PullRequest
2 голосов
/ 23 октября 2010

человек эпол:

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.

Представьте, что у нас есть два fd: первый пассивен, данные доступны только иногда, второй активен, только данные иногда недоступны.

epoll_wait вернул, что мы можем прочитать оба. Мы читаем {первое, затем второе} в цикле (без обращений к epoll_wait, поскольку он может внезапно блокироваться, пока данные еще доступны).

Теперь первый дескриптор файла вернул EAGAIN при чтении.

Что делать?

  1. Если мы продолжим чтение второго fd в цикле (без вызовов epoll_wait), мы можем упустить, что данные стали доступны на первом fd. Он будет просто читать, читать и читать без EAGAIN.
  2. Если мы будем «консультироваться» с 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

С этим я могу перечислять события для FD, даже если нет событий.

1 Ответ

0 голосов
/ 24 октября 2010

Если 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;
       }
   }
}
...