Résumé epoll LT ET

Epoll

Epoll est la base du réseau efficace de Linux.Par exemple, Event Poll (tel que nodejs) utilise libev, et la couche inférieure de libev est epoll (mais différentes plates-formes peuvent utiliser epoll ou kqueue).

epoll peut prendre en charge efficacement des millions de surveillance des poignées.

Epoll est efficace car il utilise un socket ajouté par un enregistrement d' arbre rouge-noir et utilise une liste doublement liée pour recevoir les événements déclenchés par le noyau. Pris en charge au niveau du système:

Lorsqu'un processus appelle la méthode epoll_create, le noyau Linux crée une structure eventpoll. Il y a deux membres dans cette structure qui sont étroitement liés à la façon dont epoll est utilisé.

La structure eventpoll est la suivante:

struct eventpoll{
    ....
    /*红黑树的根节点,这颗树中存储着所有添加到epoll中的需要监控的事件*/
    struct rb_root  rbr;
    /*双链表中则存放着将要通过epoll_wait返回给用户的满足条件的事件*/
    struct list_head rdlist;
    ....
};

Reportez-vous à cet article: http://blog.csdn.net/u010657219/article/details/44061629 

 

Chaque objet epoll a une structure eventpoll indépendante pour stocker les événements ajoutés à l'objet epoll via la méthode epoll_ctl.

Ces événements sont tous montés dans l'arbre rouge-noir, de sorte que les événements répétés peuvent être identifiés efficacement par l'arbre rouge-noir (l'efficacité du temps d'insertion de l'arbre rouge-noir est lgn, où n est la hauteur de l'arbre).

Et tous les événements ajoutés à epoll établiront une relation de rappel avec le pilote du périphérique (carte réseau), c'est-à-dire que cette méthode de rappel sera appelée lorsque l'événement correspondant se produira. Cette méthode de rappel est appelée ep_poll_callback dans le noyau, et elle ajoute l'événement qui se produit à la liste à double lien rdlist.

Dans epoll, pour chaque événement, une structure epitem est créée, comme indiqué ci-dessous:

struct epitem{
    struct rb_node  rbn;//红黑树节点
    struct list_head    rdllink;//双向链表节点
    struct epoll_filefd  ffd;  //事件句柄信息
    struct eventpoll *ep;    //指向其所属的eventpoll对象
    struct epoll_event event; //期待发生的事件类型
}

 

Le texte dans le coin supérieur gauche de la figure ci-dessous est erroné, il devrait être que chaque nœud de la liste doublement liée est basé sur le membre rdllink dans la structure de l'épitème. 

 

 

L'explication plus spécifique de la phrase ci-dessus est (pourquoi peut prendre en charge des millions de poignées):

1.  Pas besoin de répéter la livraison . Lorsque nous appelons epoll_wait, cela équivaut à appeler select / poll dans le passé, mais pour le moment, nous n'avons pas besoin de passer le handle de socket au noyau, car le noyau a déjà obtenu la liste des handles à surveiller dans epoll_ctl .

2. Dans le noyau, tout est un fichier . Par conséquent, epoll enregistre un système de fichiers avec le noyau pour stocker le socket surveillé mentionné ci-dessus. Lorsque vous appelez epoll_create, un nœud de fichier sera créé dans ce système de fichiers epoll virtuel. Bien sûr, ce fichier n'est pas un fichier ordinaire, il ne sert qu'à epoll.

Quand epoll est initialisé par le noyau (le système d'exploitation est démarré), il ouvrira la propre zone de cache haute vitesse du noyau d'epoll pour placer chaque socket que nous voulons surveiller. Ces sockets seront stockées dans le cache du noyau sous la forme d'un arbre rouge-noir Pour prendre en charge la recherche rapide, l'insertion et la suppression Cette zone de cache à haute vitesse du noyau sert à créer une page de mémoire physique continue, puis à y construire une couche de dalle. En termes simples, il s'agit d'allouer physiquement un objet mémoire de la taille souhaitée et d'utiliser la mémoire inactive chaque fois que vous Utilisez-le. Objets assignés.

3. Raisons de l'extrême efficacité:

En effet, lorsque nous appelons epoll_create, le noyau nous aidera non seulement à construire un nœud de fichier dans le système de fichiers epoll, et à construire un arbre rouge-noir dans le cache du noyau pour stocker la socket depuis epoll_ctl à l'avenir, mais aussi à le construire Une liste chaînée est utilisée pour stocker les événements prêts. Lorsque epoll_wait est appelé, observez simplement s'il y a des données dans cette liste chaînée. Renvoie s'il y a des données, se met en veille s'il n'y a pas de données et retourne même s'il n'y a pas de données dans la liste liée après l'expiration du délai. Par conséquent, epoll_wait est très efficace.

Comment cette liste de listes prêtes est-elle maintenue? Lorsque nous exécutons epoll_ctl, en plus de placer la socket sur l'arbre rouge-noir correspondant à l'objet fichier dans le système de fichiers epoll, nous enregistrerons également une fonction de rappel pour le gestionnaire d'interruption du noyau pour dire au noyau que si le handle du l'interruption arrive, elle le sera. Elle est placée dans la liste prête. Par conséquent, lorsqu'il y a des données sur un socket, le noyau insère le socket dans la liste prête après avoir copié les données de la carte réseau dans le noyau. (Remarque: comprenez bien cette phrase!)

Comme on peut le voir dans la phrase ci-dessus, la base d'epoll est le rappel

De cette façon, un arbre rouge-noir, une liste chaînée de descripteurs prêts et une petite quantité de cache du noyau nous aident à résoudre le problème de traitement des sockets sous une grande concurrence. Lorsque epoll_create est exécuté, un arbre rouge-noir et une liste chaînée prête sont créés. Lorsque epoll_ctl est exécuté, si le handle de socket est ajouté, vérifiez s'il existe dans l'arbre rouge-noir, s'il existe, renvoyez immédiatement, s'il n'existe pas, ajoutez-le à la jonction, puis enregistrez la fonction de rappel avec le noyau, Utilisé pour insérer des données dans la liste liée prête lorsque l'événement d'interruption survient. Lorsque epoll_wait est exécuté, les données de la liste prête peuvent être renvoyées immédiatement.

 

 

Enfin, regardez les deux modes uniques d'epoll, LT et ET. Les modèles LT et ET sont applicables aux processus mentionnés ci-dessus. La différence est que dans le mode LT, tant que l'événement sur un handle n'est pas traité à un moment, le handle sera retourné encore et encore lorsque epoll_wait sera appelé dans le futur, tandis que le mode ET ne revient que pour la première fois .

 

En ce qui concerne LT et ET, il y a une description. LT et ET sont des termes en électronique. ET est un déclenchement sur front, LT est un déclenchement horizontal. L'un signifie qu'il est déclenché uniquement sur la marge de changement, et l'autre signifie qu'il sera déclenché à un certain stade.

Reportez-vous à cet article: https://zhuanlan.zhihu.com/p/20315482

 

Pour l'expérience de code réelle de LT et ET, vous pouvez voir ici: http://www.cnblogs.com/charlesblc/p/5521086.html

À propos de ET et EPOLL_ONESHOT, vous pouvez voir ici: http://www.cnblogs.com/charlesblc/p/5538363.html

Pour le code source de l'événement unifié epoll, vous pouvez voir ici: http://www.cnblogs.com/charlesblc/p/5554785.html

 

Comment LT, ET a-t-il fait cela? Lorsqu'il y a un événement sur un handle de socket, le noyau insère le handle dans la liste liée de la liste prête mentionnée ci-dessus. À ce stade, nous appelons epoll_wait pour copier le socket prêt dans la mémoire du mode utilisateur, puis effacer la liste prête liée list, et enfin Ce que fait epoll_wait est de vérifier ces sockets, si elles ne sont pas en mode ET (c'est-à-dire le handle en mode LT), et quand il y a effectivement des événements non traités sur ces sockets, ils remettent le handle à l'état prêt liste qui vient d'être vidée. Par conséquent, pour les descripteurs non-ET, tant qu'il y a des événements, epoll_wait retournera ce descripteur à chaque fois. (D'après le paragraphe ci-dessus, on peut voir que LT a toujours un processus de lecture, ce qui est inefficace)

 

Pour un contenu plus détaillé, vous pouvez lire les deux articles suivants:

http://blog.csdn.net/russell_tao/article/details/7160071

http://www.open-open.com/lib/view/open1410403215664.html

 

Je suppose que tu aimes

Origine blog.csdn.net/qq_37061368/article/details/113259468
conseillé
Classement