Como ler vários descritores de arquivos usando epoll_select com epollet?
Pergunta
Homem 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.
Imagine que temos dois FDs: o primeiro é passivo, dados disponíveis apenas às vezes, o segundo é ativo, os dados apenas às vezes não estão disponíveis.
Epoll_wait retornou que podemos ler os dois. Lemos {o primeiro, do que o segundo} em um loop (sem chamadas para epoll_wait por causa disso pode bloquear de repente enquanto os dados ainda estão disponíveis).
Agora, o primeiro descritor de arquivo retornou a Eagin em leitura.
O que fazer?
- Se continuarmos lendo o segundo FD em um loop (sem chamadas para epoll_wait), podemos perder que os dados tenham sido disponíveis no primeiro FD. Ele apenas lerá, lerá e lerá sem Eagin.
- Se vamos "consultar" com o epoll_wait antes de ler o segundo FD, o epoll_wait poderá bloquear de repente por causa de nada mudou da chamada anterior (os dados ainda não estão disponíveis no primeiro FD e ainda estão disponíveis no segundo FD).
Como continuar processando o segundo FD, mas sem esquecer o primeiro FD?
Atualizar: Encontrei mais uma coisa: homem epoll_wait:
while specifying timeout equal to zero makes epoll_wait() to return immediately even if no events are available
Com isso, posso enumerar eventos para o FDS, mesmo que não haja eventos.
Solução
Se o FD2 for constantemente legível, você poderá considerar que o Epoll não é apropriado para isso. Pode valer a pena girar um fio apenas para sentar e lê -lo.
Caso contrário, leia o FD2 em um loop até que seja drenado, mas no loop tentam ler FD1 uma vez a cada x vezes. Se FD1 tiver dados, leia -os. Caso contrário, você apenas terá o Eagin, redefine o contador X e volte a ler o FD2. Quando ambos são drenados, você está de volta ao epoll_wait.
Algo como:
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;
}
}
}