epoll實現機制分析


 本文只介紹epoll的主要流程而不是分析源代碼,如果需要了解更多的細節可以自己翻閱相關的內核源代碼.

相關內核代碼:

fs/eventpoll.c

判斷一個tcp套接字上是否有激活事件:net/ipv4/tcp.c:tcp_poll函數


每個epollfd在內核中有一個對應的eventpoll結構對象.其中關鍵的成員是一個readylist(eventpoll:rdllist)

和一棵紅黑樹(eventpoll:rbr).

一個fd被添加到epoll中之后(EPOLL_ADD),內核會為它生成一個對應的epitem結構對象.epitem被添加到

eventpoll的紅黑樹中.紅黑樹的作用是使用者調用EPOLL_MOD的時候可以快速找到fd對應的epitem。

調用epoll_wait的時候,將readylist中的epitem出列,將觸發的事件拷貝到用戶空間.之后判斷epitem是否需

要重新添加回readylist.


epitem重新添加到readylist必須滿足下列條件:

1) epitem上有用戶關注的事件觸發.

2) epitem被設置為水平觸發模式(如果一個epitem被設置為邊界觸發則這個epitem不會被重新添加到readylist

中,在什么時候重新添加到readylist請繼續往下看).

注意,如果epitem被設置為EPOLLONESHOT模式,則當這個epitem上的事件拷貝到用戶空間之后,會將

這個epitem上的關注事件清空(只是關注事件被清空,並沒有從epoll中刪除,要刪除必須對那個描述符調用

EPOLL_DEL),也就是說即使這個epitem上有觸發事件,但是因為沒有用戶關注的事件所以不會被重新添加到

readylist中.


epitem被添加到readylist中的各種情況(當一個epitem被添加到readylist如果有線程阻塞在epoll_wait中,那

個線程會被喚醒):

1)對一個fd調用EPOLL_ADD,如果這個fd上有用戶關注的激活事件,則這個fd會被添加到readylist.

2)對一個fd調用EPOLL_MOD改變關注的事件,如果新增加了一個關注事件且對應的fd上有相應的事件激活,

則這個fd會被添加到readylist.

3)當一個fd上有事件觸發時(例如一個socket上有外來的數據)會調用ep_poll_callback(見eventpoll::ep_ptable_queue_proc),

如果觸發的事件是用戶關注的事件,則這個fd會被添加到readylist中.

了解了epoll的執行過程之后,可以回答一個在使用邊界觸發時常見的疑問.在一個fd被設置為邊界觸發的情況下,

調用read/write,如何正確的判斷那個fd已經沒有數據可讀/不再可寫.epoll文檔中的建議是直到觸發EAGAIN

錯誤.而實際上只要你請求字節數小於read/write的返回值就可以確定那個fd上已經沒有數據可讀/不再可寫.

最后用一個epollfd監聽另一個epollfd也是合法的,epoll通過調用eventpoll::ep_eventpoll_poll來判斷一個

epollfd上是否有觸發的事件(只能是讀事件).


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM