Comment un événement de socket est-il propagé / converti en epoll?

Je suis curieux de savoir comment epoll_wait () reçoit l’événement selon lequel un socket enregistré (avec epoll_ctl ()) est prêt pour la lecture / écriture.

Je crois que glibc s’en occupe comme par magie.

Ensuite, existe-t-il un document décrivant comment les événements suivants peuvent être déclenchés pour un socket?

  1. EPOLLPRI
  2. EPOLLRDNORM
  3. EPOLLRDBAND
  4. EPOLLWRNORM
  5. EPOLLWRBAND
  6. EPOLLMSG
  7. EPOLLERR
  8. EPOLLHUP
  9. EPOLLRDHUP

PS À l’origine, j’essayais de coller l’énumération EPOLL_EVENTS dans sys / epoll.h sur ma boîte ici; stackoverflow pense que je ne formate pas correctement le bloc de code même si je l’ai enveloppé de balises pre et puis code, une idée?

Le problème le plus criant de la documentation epoll est son incapacité à indiquer en “majuscules” que les événements epoll sont, en fait, totalement identiques aux événements poll (2). En effet, côté kernel, epoll traite ses événements en termes d’anciens noms d’événements de poll :

 #define POLLIN 0x0001 // EPOLLIN #define POLLPRI 0x0002 // EPOLLPRI #define POLLOUT 0x0004 // EPOLLOUT #define POLLERR 0x0008 // EPOLLERR #define POLLHUP 0x0010 // EPOLLHUP #define POLLNVAL 0x0020 // unused in epoll #define POLLRDNORM 0x0040 // EPOLLRDNORM #define POLLRDBAND 0x0080 // EPOLLRDBAND #define POLLWRNORM 0x0100 // EPOLLWRNORM #define POLLWRBAND 0x0200 // EPOLLWRBAND #define POLLMSG 0x0400 // EPOLLMSG #define POLLREMOVE 0x1000 // unused in epoll #define POLLRDHUP 0x2000 // EPOLLRDHUP 

Ensuite, une brève inspection de la source du kernel révèle que:

  • EPOLLIN et EPOLLRDNORM sont identiques (epoll renvoie EPOLLIN | EPOLLRDNORM lorsque des données sont disponibles pour la lecture à partir du descripteur de fichier).

  • EPOLLOUT et EPOLLWRNORM sont identiques (epoll renvoie EPOLLOUT | EPOLLWRNORM lorsque l’espace tampon est disponible pour l’écriture).

  • EPOLLRDBAND et EPOLLWRBAND signalent la disponibilité des données hors bande sur le descripteur (sur certaines sockets, il s’agira des données envoyées avec l’indicateur MSG_OOB passé à socket).

  • EPOLLPRI est un drapeau modificateur et augmente toujours un autre événement (tel que EPOLLERR ). Son utilisation dépend du sous-système, car cela peut vouloir dire quelque chose de différent en fonction de l’objective visé par le descripteur de fichier associé.

  • EPOLLMSG semble ne pas être utilisé par le kernel et ne sert à rien.

  • EPOLLRDHUP signale que l’homologue a fermé son côté du canal pour la lecture, mais peut toujours recevoir des données (utile pour établir qu’aucune donnée de requête EPOLLRDHUP ).

  • EPOLLHUP signale que le pair a fermé son côté du canal.

Tout le travail critique pour epoll est effectué dans le kernel, l’API de l’espace utilisateur n’est qu’une interface. Le fil de discussion précédent sur Pourquoi exactement ePoll est-il meilleur que Poll? couvre les détails de la manière dont le kernel implémente epoll c’est gentil détails.

En ce qui concerne un document décrivant les événements et leur déclenchement, la page de epoll_ctl(2) man page couvre chaque événement, par exemple:

 EPOLLIN The associated file is available for read(2) operations. EPOLLOUT The associated file is available for write(2) operations. 

Pour une meilleure description de EPOLLET vous devez lire la epoll(7) man page .

Ceci est un exemple complet d’utilisation d’epoll .

Vous utilisez epoll_ctl pour demander quels événements vous souhaitez recevoir les événements EPOLLIN et EPOLLET , le code ci-dessus fait ceci:

 event.events = EPOLLIN | EPOLLET; s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event);