在我的博文《linux的select poll epoll的io多路復用》中介紹過:
level-triggered即條件觸發,只要滿足事件的條件,比如有資料需要讀,就一直不斷地把這個事件傳遞給使用者;
edge-triggered即邊緣觸發,只有第一次滿足條件的時候才觸發,之後就不會再傳遞同樣的事件了。一般來說邊緣觸發的效率比條件觸發的效率要高。
從上文的博文中可以看出,在 ep_send_events_proc 函式的最後,針對 level-triggered 情況,當前的 epoll_item 物件被重新加到 eventpoll 的就緒列表中,這樣在下一次 epoll_wait 呼叫時,這些 epoll_item 物件就會被重新處理。又由於,在最終拷貝到使用者空間有效事件列表中之前,會呼叫對應檔案的 poll 方法,以確定這個事件是不是依然有效。所以,如果使用者空間程式已經處理掉該事件,就不會被再次通知,但是會導致epoll_wait空跑一次;如果沒有處理,意味著該事件依然有效,就會被再次通知。
這就是為什麼我們說edge-triggered效率會高一些。
1、poll/select 先將要監聽的 fd 從使用者空間拷貝到核心空間, 然後在核心空間裡面進行處理之後,再拷貝給使用者空間。這裡就涉及到核心空間申請記憶體,釋放記憶體等等過程,這在大量 fd 情況下,是非常耗時的。而 epoll 維護了乙個紅黑樹,通過對這棵黑紅樹進行操作,可以避免大量的記憶體申請和釋放的操作,而且查詢速度非常快。
2、select/poll 從休眠中被喚醒時(某個描述符發生事件,時間片到,發生訊號),核心就會遍歷內部的 list 去檢查到底是哪乙個事件到達,並沒有像 epoll 一樣, 通過 fd 直接關聯 eventpoll 物件,快速地把 fd 直接加入到 eventpoll 的就緒列表中。
3、poll/select返回時,需要遍歷fd集合,以查詢哪些fd上面有事件發生,而epoll直接返回有事件的集合。
補充一下epoll事件的觸發時機
1.水平觸發的時機
對於讀操作,只要緩衝內容不為空,lt模式返回讀就緒;
對於寫操作,只要緩衝區還不滿,lt模式會返回寫就緒。
2.邊緣觸發的時機
對於讀操作
當緩衝區由不可讀變為可讀的時候,即緩衝區由空變為不空的時候;
當有新資料到達時,即緩衝區中的待讀資料變多的時候;
當緩衝區有資料可讀,且應用程序對相應的描述符進行epoll_ctl_mod 修改epollin事件時。
對於寫操作
當緩衝區由不可寫變為可寫時;
當有舊資料被傳送走,即緩衝區中的內容變少的時候;
當緩衝區有空間可寫,且應用程序對相應的描述符進行epoll_ctl_mod 修改epollout事件時。
從I O復用談epoll為什麼高效
很多人提到網路就說epoll,認為epoll效率是最高的。單純的這麼認為,其實有失偏頗。epoll固然高效,可是它是怎麼做到高效的,它到底比select或poll優異在哪兒?我們通過呼叫流程來簡單分析下。首先以select為例 poll類似 看下其呼叫過程 1.選擇想要處理的套接字,通過介面fd s...
epoll為什麼快
epoll是linux下的一種i o多路復用的操作方式,是event poll的意思 i o多路復用,舉個栗子,在酒吧,乙個服務員,10個顧客在喝酒,服務員有這麼幾種服務方式 服務員從第乙個顧客開始問,你要酒嗎,再問第二個,你要酒嗎,依次問下去,問完一圈,再從頭開始,服務員就是不停的在bbb,要酒嗎...
為什麼需要epoll
首先我們來定義流的概念,乙個流可以是檔案,socket,pipe等等可以進行i o操作的核心物件。不管是檔案,還是套接字,還是管道,我們都可以把他們看作流。之後我們來討論i o的操作,通過read,我們可以從流中讀入資料 通過write,我們可以往流寫入資料。現在假定乙個情形,我們需要從流中讀資料,...