[英]Are epoll events being watched when not epoll_waiting
我對基於事件的編程很陌生。 我正在嘗試使用epoll
的edge-mode ,它顯然只發出已准備好進行讀/寫的信號(與level-mode相對,它發出所有准備好的文件的信號,無論是否已經准備好或剛剛准備就緒) 。
我不清楚的是: 在邊緣模式下,我是否被告知當我沒有epoll_wait
ing時發生的准備事件? 尚未恢復的單發文件事件如何處理?
為了說明我為什么要問這個問題,請考慮以下情形:
epoll_ctl
當所述插座是准備用於讀,在邊緣模式+單穩反應: EPOLLET | EPOLLONESHOT | EPOLLIN
EPOLLET | EPOLLONESHOT | EPOLLIN
epoll_wait
等待某事發生(最多報告10個事件) read
並處理了數據套接字#1(直到E_AGAIN
) read
並處理了數據套接字2(直到E_AGAIN
) EPOLL_CTL_MOD
模式下使用epoll_ctl
重新觸發了文件 epoll_wait
, epoll_wait
下一批事件 好的, epoll_wait
總是將套接字S的就緒狀態通知給最后一個epoll_wait
? 如果S為#1(即不重新設置),是否會發生事件?
我正在嘗試使用epoll的邊緣模式,該模式顯然僅信號通知已准備好進行讀/寫的文件(與級別模式相反,該信號通知所有准備就緒的文件,無論是否已經准備就緒或剛剛准備就緒)
首先,讓我們對系統有一個清晰的了解,您需要一個關於系統如何工作的准確的思維模型。 您對epoll(7)
看法並不十分准確。
邊沿觸發和電平觸發之間的區別在於對事件產生原因的定義。 前者為已在文件描述符上預訂的每個動作生成一個事件。 一旦您使用了該事件,它就消失了-即使您沒有使用所有生成此類事件的數據。 OTOH,后者會不斷重復生成同一事件,直到您消耗掉生成該事件的所有數據為止。
這是一個將這些概念付諸實踐的示例,這些概念被公然自man 7 epoll
竊取了:
代表管道(rfd)讀取端的文件描述符在epoll實例上注冊。
管道寫入器在管道的寫入側寫入2 kB的數據。
完成對epoll_wait(2)的調用,該調用將返回rfd作為就緒文件描述符。
管道讀取器從rfd讀取1 kB數據。
對epoll_wait(2)的調用已完成。
如果已使用EPOLLET(邊緣觸發)標志將rfd文件描述符添加到epoll接口,則盡管文件輸入緩沖區中仍然存在可用數據,但步驟5中對epoll_wait(2)的調用可能會掛起; 同時,遠程對等端可能希望根據已發送的數據做出響應。 原因是邊緣觸發模式僅在受監視的文件描述符發生更改時才傳送事件。 因此,在步驟5中,調用方可能最終等待輸入緩沖區中已經存在的某些數據。 在上面的示例中,由於在2中完成寫操作,因此將在rfd上生成一個事件,並且該事件在3中使用。由於在4中完成的讀取操作不會消耗整個緩沖區數據,因此對epoll_wait(2)的調用已完成在第5步中可能會無限期屏蔽。
簡而言之,根本的區別在於“事件”的定義:邊緣觸發將事件視為您消耗一次的單個單位; 級別觸發將事件的消耗定義為等同於消耗屬於該事件的所有數據。
現在,讓我們解決您的特定問題。
在邊緣模式下,我是否得知在不epoll_waiting時發生的准備事件
是的,你是。 在內部,內核將每個文件描述符上發生的有趣事件排隊。 它們在下次調用epoll_wait(2)
,因此您可以放心,您不會丟失任何事件。 好吧,如果還有其他未決事件並且傳遞給epoll_wait(2)
的事件緩沖區無法容納所有事件,則可能不完全在下一個調用中,但是關鍵是最終將報告這些事件。
尚未恢復的單發文件事件如何處理?
同樣,您永遠不會輸掉任何事件。 如果還沒有恢復文件描述符,那么如果發生任何有趣的事件,它只會在內存中排隊,直到恢復文件描述符為止。 一旦重新進入工作狀態,任何未決的事件-包括那些描述符被重新進入工作狀態之前發生了-將被報告到下一次調用epoll_wait(2)
再次,也許不完全是下一個,但他們會報)。 換句話說, EPOLLONESHOT
不會禁用事件監視,它只是暫時禁用事件通知 。
好的,那么是否總是將套接字S的就緒狀態通知給最后一個epoll_wait? 如果S為#1(即不重新設置),會發生事件嗎?
鑒於我上面所說的,現在應該很清楚:是的,它將。 您不會丟失任何事件。 epoll提供了有力的保證,這很棒。 它也是線程安全的,您可以在不同線程中等待同一epoll fd並同時更新事件訂閱。 epoll非常強大,值得花時間學習它!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.