epoll與select、poll差別
1、相比于select與poll,epoll最大的好處在于它不會随着監聽fd數目的增長而降低效率。核心中的select與poll的實作是采用輪詢來處理的,輪詢的fd數目越多,自然耗時越多。
2、epoll的實作是基于回調的,如果fd有期望的事件發生就通過回調函數将其加入epoll就緒隊列中,也就是說它隻關心“活躍”的fd,與fd數目無關。
3、epoll不僅會告訴應用程式有I/0 事件到來,還會告訴應用程式相關的資訊,這些資訊是應用程式填充的,是以根據這些資訊應用程式就能直接定位到事件,而不必周遊整個fd集合。
4、當已連接配接的套接字數量不太大,并且這些套接字都非常活躍,那麼對于epoll 來說一直在調用callback 函數(epoll 内部的實作更複雜,更複雜的代碼邏輯),可能性能沒有poll 和 select 好,因為一次性周遊對活躍的檔案描述符處理,在連接配接數量不大的情況下,性能更好,但在處理大量連接配接的情況時,epoll 明顯占優。
epoll 的EPOLLLT (level-trigger 水準觸發,預設)和 EPOLLET(edge-trigger 邊沿觸發)模式的差別
二者的差異在于 level-trigger 模式下隻要某個 fd 處于 readable/writable 狀态,無論什麼時候進行 epoll_wait 都會傳回該 fd;而 edge-trigger 模式下隻有某個 fd 從 unreadable 變為 readable 或從 unwritable 變為 writable 時,epoll_wait 才會傳回該 fd。
1、EPOLLLT:完全靠kernel epoll驅動,應用程式隻需要處理從epoll_wait傳回的fds,這些fds我們認為它們處于就緒狀态。此時epoll可以認為是更快速的poll。
2、EPOLLET:此模式下,系統僅僅通知應用程式哪些fds變成了就緒狀态,一旦fd變成就緒狀态,epoll将不再關注這個fd的任何狀态資訊,(從epoll隊列移除)直到應用程式通過讀寫操作(非阻塞)觸發EAGAIN狀态(EAGAIN:所要求的資源暫時不可用;如果稍後再嘗試此操作,則可能會成功。),epoll認為這個fd又變為空閑狀态,那麼epoll又重新關注這個fd的狀态變化(重新加入epoll隊列)。随着epoll_wait的傳回,隊列中的fds是在減少的,是以在大并發的系統中,EPOLLET更有優勢,但是對程式員的要求也更高,因為有可能會出現資料讀取不完整的問題,舉例如下:
假設現在對方發送了2k的資料,而我們先讀取了1k,然後這時調用了epoll_wait,如果是邊沿觸發,那麼這個fd變成就緒狀态就會從epoll 隊列移除,很可能epoll_wait 會一直阻塞,忽略尚未讀取的1k資料,與此同時對方還在等待着我們發送一個回複ack,表示已經接收到資料;如果是電平觸發,那麼epoll_wait 還會檢測到可讀事件而傳回,我們可以繼續讀取剩下的1k 資料。
注:上述使用 epoll ET 的例子隻是個示例,更規範的用法可以參考這裡。
原文連結:點選打開連結