0Pricing
C Academy · Aula

Configurando epoll

Crie e registre um conjunto epoll.

Configurando epoll é uma aula grátis de C Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C Academy inclui 4 aulas no total.

Criando uma instância de epoll

Tudo começa com uma instância de epoll, que é, por si só, um descritor de arquivo. Crie uma usando epoll_create1().

O argumento é um campo de sinalizadores; passe 0 para o comportamento padrão ou EPOLL_CLOEXEC para fechar o descritor automaticamente durante exec(). O fd retornado é o que você passa para todas as outras chamadas de epoll.

int epfd = epoll_create1(EPOLL_CLOEXEC);
if (epfd == -1) { perror("epoll_create1"); exit(1); }

epoll_create1 versus epoll_create

A função mais antiga epoll_create(int size) recebia uma indicação de tamanho, mas o kernel a ignora atualmente; o único requisito era que ela fosse positiva.

Prefira epoll_create1(): ela recebe sinalizadores em vez de um tamanho sem significado e permite solicitar EPOLL_CLOEXEC atomicamente, evitando uma chamada separada a fcntl().

/* legacy form, size arg ignored by kernel */
int epfd = epoll_create(1);

A estrutura epoll_event

Tanto o interesse quanto os resultados são expressos por meio de struct epoll_event. Ela tem uma máscara de bits events e uma união data.

A união data armazena o que você quiser que seja retornado quando o evento ocorrer: normalmente data.fd, mas também pode ser um data.ptr apontando para um objeto de conexão que você alocou.

struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = listen_fd;

Registrando com EPOLL_CTL_ADD

epoll_ctl() gerencia a lista de interesses. Use a operação EPOLL_CTL_ADD para começar a monitorar um descritor.

Você passa o fd de epoll, a operação, o fd de destino e um ponteiro para seu epoll_event. Depois disso, epoll informará quando o descritor estiver pronto.

struct epoll_event ev = { .events = EPOLLIN, .data.fd = listen_fd };
if (epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev) == -1)
    perror("epoll_ctl: add");

Sinalizadores de eventos: EPOLLIN e EPOLLOUT

A máscara events indica o que lhe interessa. EPOLLIN significa que o descritor está pronto para leitura; EPOLLOUT significa que ele está pronto para escrita.

Normalmente, você monitora EPOLLIN em um soquete de escuta (para aceitar conexões) e em soquetes de clientes (para ler). Adicione EPOLLOUT somente quando houver dados armazenados em buffer que não tenham sido enviados completamente.

ev.events = EPOLLIN | EPOLLOUT;

Sinalizadores de erro e desligamento

O kernel sempre informa determinadas condições, mesmo que você não as tenha solicitado: EPOLLERR para erros, EPOLLHUP para um desligamento e EPOLLRDHUP para um meio-desligamento realizado pelo par.

Verifique esses sinalizadores no seu manipulador; ignorar EPOLLHUP em um soquete morto faz o loop de eventos executar repetidamente sem necessidade.

if (ev.events & (EPOLLERR | EPOLLHUP)) {
    close(ev.data.fd);
    continue;
}

Modificando o interesse com EPOLL_CTL_MOD

Depois que um descritor é registrado, você pode alterar sua máscara de eventos sem removê-lo. Use EPOLL_CTL_MOD.

Um padrão comum é: uma conexão normalmente monitora apenas EPOLLIN; depois, muda para EPOLLIN | EPOLLOUT quando o buffer de envio fica cheio e volta ao estado anterior assim que é esvaziado.

ev.events = EPOLLIN | EPOLLOUT;
ev.data.fd = conn_fd;
epoll_ctl(epfd, EPOLL_CTL_MOD, conn_fd, &ev);

Removendo com EPOLL_CTL_DEL

Quando uma conexão é fechada, pare de monitorá-la com EPOLL_CTL_DEL. O argumento final epoll_event é ignorado e pode ser NULL nos kernels modernos.

Observe que fechar um descritor o remove automaticamente de todas as listas de interesse do epoll, mas excluí-lo explicitamente antes de fechá-lo mantém seu controle interno mais claro.

epoll_ctl(epfd, EPOLL_CTL_DEL, conn_fd, NULL);
close(conn_fd);

Orientado por nível versus orientado por borda

Por padrão, epoll é orientado por nível: enquanto um descritor permanecer pronto para leitura, cada chamada a epoll_wait() o informará. Esse modo é tolerante e fácil de usar.

Adicione o sinalizador EPOLLET para usar o modo orientado por borda: você só será notificado quando o estado de prontidão mudar, portanto deverá esvaziar completamente o soquete em um loop até receber EAGAIN.

ev.events = EPOLLIN | EPOLLET;  /* edge-triggered */
epoll_ctl(epfd, EPOLL_CTL_ADD, conn_fd, &ev);

Armazenando um ponteiro de contexto

Em vez de data.fd, você pode armazenar data.ptr apontando para uma estrutura específica da conexão. Quando o evento ocorrer, você receberá esse ponteiro diretamente, sem precisar de uma tabela de consulta.

Lembre-se apenas da união: se você definir data.ptr, também não poderá ler data.fd do mesmo evento.

struct conn *c = malloc(sizeof *c);
c->fd = conn_fd;
ev.events = EPOLLIN;
ev.data.ptr = c;
epoll_ctl(epfd, EPOLL_CTL_ADD, conn_fd, &ev);

Limpeza

A instância de epoll é apenas um descritor de arquivo, portanto você a libera com close() quando o servidor for encerrado.

Fechar o fd de epoll libera a lista de interesses do kernel. Quaisquer soquetes monitorados que ainda estejam abertos permanecem abertos; feche-os separadamente para liberar seus recursos.

close(epfd);

Verificação rápida

Teste seu domínio da API de configuração do epoll.

Recapitulação

Você cria uma instância com epoll_create1() e depois gerencia o interesse por meio de epoll_ctl(), usando ADD, MOD e DEL. Cada struct epoll_event contém uma máscara events e uma união data.

Escolha o modo orientado por nível pela simplicidade ou EPOLLET pelo desempenho do modo orientado por borda. Em seguida, usaremos esses componentes em um loop de eventos.

Perguntas Frequentes

A aula “Configurando epoll” é grátis?

Sim — o texto completo de “Configurando epoll” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C Academy, atualize para CoddyKit PRO. O curso de C Academy inclui 4 aulas no total.

O que vou aprender em “Configurando epoll”?

Crie e registre um conjunto epoll. Você pratica C Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar C Academy?

Nenhuma experiência prévia é necessária. C Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “Configurando epoll”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de C Academy?

Sim. Cada aula de C Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. E/S bloqueante versus não bloqueante
  2. Configurando epoll
  3. O laço de eventos
  4. Um servidor de eco simples
← Voltar para C Academy