Epoll in EPOLLET Modus zurückkehrt 2 EPOLLIN, bevor sie aus der Buchse Lesen
-
28-09-2019 - |
Frage
Die epoll manpage sagt, dass ein fd mit EPOLLET registriert (flankengetriggert) nicht zweimal EPOLLIN benachrichtigen, wenn keine Lese getan wurde.
Also nach einem EPOLLIN müssen Sie den Puffer leeren, bevor epoll_wait in der Lage, eine neue EPOLLIN auf neue Daten zurückzukehren.
Allerdings erlebe Ich habe Probleme mit diesem Ansatz, wie ich sehe duplizierten EPOLLIN Veranstaltungen für unberührten fds.
Dies ist der Strace Ausgang, 0x200 EPOLLRDHUP ist, die noch nicht in meinen glibc-Header definiert, aber im Kern definiert.
30285 epoll_ctl(3, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET|0x2000, {u32=9, u64=9}}) = 0
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3, <unfinished ...>
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = 0
30306 recv(9, "7u\0\0\10\345\241\312\t\20\f\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30"..., 20000, 0) = 20000
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = -1 ENOENT (No such file or directory)
30305 recv(9, " \31(C0\17\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30\200\10 \31("..., 20000, 0) = 10011
Also, nach der Zugabe von fd Nummer 9 Ich erhalte 2 aufeinander folgende EPOLLIN Ereignisse bevor mit dem Dateideskriptor recving, die syscall Spur zeigt, wie ich das fd tun löschen, bevor das Lesen, aber es sollte nur einmal geschehen, ein pro Veranstaltung.
Also entweder ich bin nicht auf die Hilfeseite richtig zu lesen oder etwas arbeitet jetzt hier.
Lösung
Ich glaube, du diesen Teil der epoll
Manpage verpasst haben:
Da auch bei der flankengetriggerter epoll können mehrere Ereignisse erzeugt werden bei Empfang von mehreren Stücken von Daten, hat der Anrufer die Möglichkeit, geben die
EPOLLONESHOT
Flag, um sagen epoll die zugehörige deaktivieren Dateideskriptors nach dem Empfang ein Ereignis mitepoll_wait(2)
. Wann derEPOLLONESHOT
Flag angegeben wird, es liegt in der Verantwortung des Anrufers an bewaffnen den Dateideskriptor mitepoll_ctl(2)
mitEPOLL_CTL_MOD
.
Das heißt: Sie bekam zwei Stücke von Daten in Ihrer Empfangswarteschlange ankommen, bevor Sie Ihren ersten read()
passiert ist, das heißt, Sie zwei epoll Ereignisse bekam. Es scheint, wie EPOLLONESHOT
ist, was Sie nach, was atomar den Dateideskriptor aus der Umfrage Satz entfernen, wenn ein Ereignis auf es passiert (so dass Sie nicht brauchen die EPOLL_CTL_DEL
zu tun).
Andere Tipps
Flankentrigger einfach Mittel (es sei denn, Sie gebrauchte EPOLLONESHOT haben), dass Sie ein Ereignis erhalten, wenn etwas eintritt, das (Kernel) puffern.
Wenn Sie also 1 EPOLLIN Veranstaltung erhalten und tun nichts dagegen, Sie eine andere EPOLLIN das nächste Mal kommt einige Daten auf diesem Descriptor bekommen - wenn keine neue Daten ankommen, werden Sie nicht ein Ereignis aber, auch wenn Sie lesen konnten keine Daten durch das erste Ereignis angezeigt wird.
Nun, um es kurz und bündig, EPOLLONESHOT nur bedeutet, dass, wenn Sie die Daten nicht lesen kann man eigentlich sind lesen, werden sie verworfen werden.
Normalerweise würde man mit einem Ereignis für die gleichen Daten benachrichtigt, wenn Sie sie nicht lesen. Mit EPOLLONESHOT jedoch nicht die Daten zu lesen ist vollkommen legal und werden sie einfach ignoriert werden. Daher werden keine weiteren Ereignisse erzeugt werden.