0Pricing
C Academy · Lección

Configurar epoll

Cree y registre un conjunto epoll

Configurar epoll es una lección gratuita de C Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C Academy incluye 4 lecciones en total.

Creación de una instancia de epoll

Todo comienza con una instancia de epoll, que a su vez es un descriptor de archivo. Créela con epoll_create1().

El argumento es un campo de indicadores; pase 0 para el comportamiento predeterminado o EPOLL_CLOEXEC para cerrar el descriptor automáticamente al ejecutar exec(). El fd devuelto es el que debe pasar a todas las demás llamadas de epoll.

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

epoll_create1 frente a epoll_create

La función anterior epoll_create(int size) recibía una sugerencia de tamaño, pero el kernel la ignora actualmente; el único requisito era que fuera positiva.

Prefiera epoll_create1(): recibe indicadores en lugar de un tamaño sin significado y permite solicitar EPOLL_CLOEXEC de forma atómica, evitando una llamada independiente a fcntl().

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

La estructura epoll_event

Tanto los eventos de interés como los resultados se expresan mediante struct epoll_event. Contiene una máscara de bits events y una unión data.

La unión data contiene lo que desee recibir cuando se produzca el evento: normalmente data.fd, aunque también puede ser un data.ptr que apunte a un objeto de conexión que haya reservado.

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

Registro con EPOLL_CTL_ADD

epoll_ctl() administra la lista de interés. Use la operación EPOLL_CTL_ADD para empezar a supervisar un descriptor.

Debe pasar el fd de epoll, la operación, el fd de destino y un puntero a su epoll_event. Después de esto, epoll informará cuando el descriptor esté listo.

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");

Indicadores de eventos: EPOLLIN y EPOLLOUT

La máscara events indica qué condiciones le interesan. EPOLLIN significa que el descriptor se puede leer; EPOLLOUT significa que se puede escribir en él.

Normalmente se supervisa EPOLLIN en un socket de escucha, para aceptar conexiones, y en los sockets de los clientes, para leer. Añada EPOLLOUT únicamente cuando tenga datos almacenados en búfer que no se hayan enviado por completo.

ev.events = EPOLLIN | EPOLLOUT;

Indicadores de error y cierre

El kernel siempre informa de determinadas condiciones, aunque no las haya solicitado: EPOLLERR para los errores, EPOLLHUP para un cierre y EPOLLRDHUP para un cierre parcial por parte del par.

Compruebe estas condiciones en su controlador; ignorar EPOLLHUP en un socket cerrado provoca un ciclo continuo en el bucle de eventos.

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

Modificación del interés con EPOLL_CTL_MOD

Una vez registrado un descriptor, puede cambiar su máscara de eventos sin eliminarlo. Use EPOLL_CTL_MOD.

Un patrón habitual es que una conexión supervise normalmente solo EPOLLIN; después cambie a EPOLLIN | EPOLLOUT cuando se llene su búfer de envío y vuelva a cambiar cuando se haya vaciado.

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

Eliminación con EPOLL_CTL_DEL

Cuando se cierra una conexión, deje de supervisarla con EPOLL_CTL_DEL. El argumento final epoll_event se ignora y puede ser NULL en los kernels modernos.

Tenga en cuenta que cerrar un descriptor lo elimina automáticamente de cualquier lista de interés de epoll, pero eliminarlo explícitamente antes de cerrarlo mantiene claro el control de los recursos.

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

Activación por nivel frente a activación por flanco

De forma predeterminada, epoll utiliza activación por nivel: mientras un descriptor siga pudiéndose leer, cada llamada a epoll_wait() lo informará. Es un comportamiento tolerante y sencillo.

Añada el indicador EPOLLET para usar la activación por flanco: solo recibirá una notificación cuando cambie el estado de disponibilidad, por lo que debe vaciar completamente el socket en un bucle hasta EAGAIN.

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

Almacenamiento de un puntero de contexto

En lugar de data.fd, puede almacenar data.ptr apuntando a una estructura propia de cada conexión. Cuando se produzca el evento, recibirá directamente ese puntero, sin necesidad de una tabla de búsqueda.

Recuerde que se trata de una unión: si establece data.ptr, no puede leer también data.fd del mismo 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);

Liberación de recursos

La instancia de epoll es simplemente un descriptor de archivo, por lo que debe liberarla con close() cuando se cierre el servidor.

Al cerrar el fd de epoll se libera la lista de interés del kernel. Los sockets supervisados que sigan abiertos permanecen abiertos; ciérrelos por separado para liberar sus recursos.

close(epfd);

Comprobación rápida

Compruebe cuánto ha entendido de la API de configuración de epoll.

Resumen

Debe crear una instancia con epoll_create1() y administrar después el interés mediante epoll_ctl(), usando ADD, MOD y DEL. Cada struct epoll_event contiene una máscara events y una unión data.

Elija la activación por nivel por su sencillez o EPOLLET para obtener el rendimiento de la activación por flanco. A continuación, utilizaremos estas piezas desde un bucle de eventos.

Preguntas frecuentes

¿La lección «Configurar epoll» es gratis?

Sí — el texto completo de «Configurar epoll» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C Academy, actualiza a CoddyKit PRO. El curso de C Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Configurar epoll»?

Cree y registre un conjunto epoll Practicas C Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C Academy?

No se requiere experiencia previa. C Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.

¿Cuánto tiempo toma la lección «Configurar epoll»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C Academy?

Sí. Cada lección de C Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. E/S bloqueante frente a no bloqueante
  2. Configurar epoll
  3. El bucle de eventos
  4. Un servidor de eco sencillo
← Volver a C Academy