Linux 學習筆記之 --- epoll 事件模型詳解


 

epoll 主要采用對已就緒的 fd 進行輪詢操作
 
一、epoll 觸發方式
epoll支持 ET 和 LT 兩種觸發方式
ET(邊緣觸發):Nginx 就是采用 ET 觸發方式,只支持 no-block 方式,當一個 fd 緩沖區就緒的時候,只會發送一次事件觸發, 而不會管緩沖區的數據是否已經被讀取,都不會再發送第二次
LT(邊緣觸發):支持no-block 和 block 兩種方式,當一個 fd 緩沖區就緒時,只要緩沖區有數據,就會不停的發送就緒通知
 
二、epoll 相關函數:
2.1、int epoll_create(int size);
用於創建一個 epoll 句柄,創建一個 epoll 句柄之后,會占用一個 fd 描述符,對於一個進程來說,它相關的 fd 描述符可以查看/proc/進程id/fd/, 在使用完epoll 之后,需要對他進行 close ,否則會導致 fd 太多被耗盡
 
2.2、int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
事件注冊函數,將 fd 添加、修改、刪除到 epfd 中,通過 op 參數修改
EPOLL_CTL_ADD:注冊新的fd到epfd中;
EPOLL_CTL_MOD:修改已經注冊的fd的監聽事件;
EPOLL_CTL_DEL:從epfd中刪除一個fd;
 
2.3、int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
可以理解為收集epoll 監控的所有事件中,已經發生的那部分 fd 的數量
 
三、epoll 工作原理
3.1、在調用 epoll_create 之后,內核就已經創建了一個 eventpoll 紅黑樹結構體,一個 list 雙向鏈表,在內核態准備接受存儲需要監控的 fd。
3.2、在調用 epoll_ctr 之后,直接向內核態的 eventpoll 進行 add/mod/del 對應的 fd,對於新添加進來的 fd,重復的 fd 可以通過 eventpoll 紅黑樹識別出來,而不需要再次從用戶態拷貝到內核態這個過程
3.3、同時 epoll 還維護了一個雙向的 list 鏈表, 在epoll_ctr執行的時候,除了會向eventpoll 紅黑樹添加修改外,還會在內核中斷函數處理程序中注冊一個回調函數,告訴內核,當這個 fd 就緒之后,將他放到 list 里面去。
3.4、在 epoll_wait 調用的時候,就是觀察這個雙向 list 是否有數據,有就直接處理即可
 
四、偽代碼
1 fd = socket_connect()  #建立一個網絡連接
2 efd = epoll_create(0)   #創建一個epoll
3 epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event)  #將網絡連接 fd 添加到efd中
4 n = epoll_wait(efd, events, MAXEVENTS, -1) #從 list 中獲取已經就緒的 fd 的數量
5 for i in range(n):
6     ev = events[i]   # 從events 內存中獲取已經就緒的 fd,執行相關操作
7     doing(ev)

 

 
五、優點
5.1、沒有 fd 數量限制,取決於系統內存的大小,一般來說 1GB 就可以有 10W個
5.2、內核和用戶控件使用同一塊內存,mmap技術,沒有用戶態和內核態之間的拷貝,提高效率
5.3、無需遍歷所有,僅僅只需要遍歷已經就緒的 fd 即可
 
 
 
 
 
 
 
 
 


免責聲明!

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



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