epoll和他的兄弟們

解釋一下epoll與select的區別

epoll和select都是linux下的IO多路複用模型,主要用於實現併發服務程序

相對於select/poll來說,epoll能顯著提高程序在大量併發連接中只有少量活躍的情況下cpu的利用率,這主要是因爲他們使用的數據結構以及工作方式是不同。

select需要read、write、error三個數組來告訴內核監聽的事件類型

while(1){
	初始化文件描述符到集合
	將活動句柄加入到文件描述符中
	調用select函數,fd集合拷貝到內核{
		return ready_count;
	}
	然後輪詢整個數組找到需要處理的事件進行處理
}

epoll使用event結構體來標記fd的事件類型等等,主要有三個系統調用函數

	//創建一個epoll文件描述符
	epoll_create(int maxfds);
	//添加/修改/刪除需要偵聽的文件描述符及其事件,實際上是向紅黑樹中增刪改節點
	epoll_ctl
	//接收發生在被偵聽的描述符上的,用戶感興趣的IO事件
	epoll_wait(int epfd, epoll_event *events, int max events, int timeout){
	    return ready_list;
	}
	輪詢ready_list處理相關事件

select每次調用都要將fd集合從用戶態拷貝到內核態
而epoll只需要向內核態拷貝一次即可
結論:epoll內核態與用戶態切換次數更少,運行效率更高

select能夠管理的文件描述符的數量爲一個進程能夠打開的文件描述符的數量,在1024左右
而epoll是在高速內存中保存紅黑樹節點,能夠管理的文件描述符數量取決於內存大小,遠大於2048,在1G內存中大概是1萬左右
結論:epoll更適合大量併發連接

select數據結構是數組,而epoll是紅黑樹+list
select不斷輪詢所有的fd集合直到有設備就緒,返回就緒數,隨着數組的增大處理效率會降低
而epoll只需要輪詢就緒鏈表直到有數據就緒,這是因爲每個fd都會有相應的回調函數,在socket活躍時調用,並將其放入ready_list中,處理效率不會隨fd數目增大而降低
總結:epoll的IO處理效率更高更穩定

select在內核將fd消息通知用戶空間的時候進行了內存拷貝
epoll通過內核與用戶空間mmap同一塊內存避免了拷貝,加速了內核與用戶空間的消息傳遞
總結:epoll在內核與用戶空間的消息傳遞的速度上更快

mmap :一種內存映射文件的方法

ET與LT
select採用水平觸發方式,如果有fd就緒,如果你不做任何操作內核會繼續通知你,這種編程方式出錯可能性小一點。
epoll可以採用邊緣出發或者水平觸發方式,默認是水平觸發邊緣觸發方式在fd就緒後內核只會通知一次,除非該fd不再爲就緒狀態,這樣的話維護的ready_list長度更低,效率更高,但是有可能帶來一次不處理以後都不會被處理的問題。

但並不是所有的情況下epoll都是優於select的:
連接數較少而且比較活躍情況下更適合使用select
epoll每個事件都要註冊一個回調函數有一定的開銷,運行機制更加複雜。

阻塞、非阻塞,同步、異步

內核態和用戶態

參考鏈接:
Epoll在LT和ET模式下的區別以及注意事項.
網絡高併發服務器之epoll接口、epoll反應堆模型詳解及代碼實現.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章