1. 程式人生 > >select、poll、epoll的區別

select、poll、epoll的區別

成員 監聽 logs 最大 nts href huang 工作 工作模式

本文寫於2017-02-26,從老賬號遷移到本賬號,原文地址:https://www.cnblogs.com/huangweiyang/p/6444746.html

select、poll、epoll三組系統調用都能同時監聽多個文件描述符,它們將等待由timeout參數指定的超時時間,直到一個或多個文件描述符上有事件時返回,返回值是就緒的文件描述符的數量。返回0表示沒有事件發生。

下面從事件集、最大支持文件描述符數、工作模式和具體實現等四個方面進一步比較它們的異同。

事件集:

select的參數類型fd_set沒有將文件描述符和事件綁定(沒有用數據結構綁定fd和event),它僅僅是一個文件描述符集合,因此select需要提供3個這種類型的參數來分別傳入可讀、可寫及異常事件。一方面這使得select不能處理更多類型的事件,另一方面由於內核對fd_set集合的在線修改,應用程序下次調用select前不得不重置這3個fd_set集合。

poll參數類型pollfd結構體將文件描述符和事件綁定起來,任何事件都被統一處理,並且內核每次修改的都是pollfd結構體的revents成員,而events成員不變,因此下次調用poll時應用程序無需重置pollfd。

由於每次select和poll調用都返回整個用戶註冊的事件集合(其中包括就緒的和未就緒的),所以應用程序索引就緒文件描述符的時間復雜度為O(n)。

epoll則采用與select和poll完全不同的方式來管理用戶註冊的事件。它在內核中維護一個事件表,並提供了一個獨立的系統調用epoll_ctl來控制往其中添加、註冊、修改事件。這樣,每次epoll_wait調用都直接從內核事件表中取得用戶註冊的時間,而無需反復從用戶空間讀入這些事件。epoll_wait系統調用的events參數僅用來返回就緒的時間,應用程序索引文件描述符時間復雜度為O(1)。

工作模式

select和poll都只能工作在相對低效的LT模式,而epoll則可以工作在ET高效模式,並且epoll還支持EPOLLONESHOT事件。該事件能進一步減少可讀、可寫、異常事件被觸發的次數。

實現原理

從實現原理上來說,select和poll采用的都是輪詢的方式,即每次調用都要掃描整個註冊文件描述符集合,並將其中就緒的文件描述符返回給用戶程序,因此他們檢測就緒事件的時間復雜度是O(n)。epoll則不同,當我們使用epoll_ctl註冊事件時,epoll內部會把socket封裝成為epitem插入到紅黑樹之中,還會給內核中斷處理程序註冊一個回調函數。當socket上有事件時,內核會把對應的epitem插入到rdlist中,epoll_wait檢測rdlist不為空,就將該就緒隊列的內容拷貝到用戶空間。(如果是LT模式,在拷貝之後還會將epitem重新加入rdlist)。因此,epoll_wait不必輪詢整個文件描述符集合,算法時間復雜讀是O(1)。但是,活動鏈接比較多時,epoll_wait未必比select和poll高,因為此時回調函數觸發過於頻繁。所以epoll_wait適用於連接數量多,但活動連接較少的情況。

如下表:

系統調用 select poll epoll
事件集合 用戶通過3個參數分別傳入感興趣的可讀、可寫及異常等事件,內核通過對著寫參數的在線修改來反饋其中的就緒事件。這是用用戶每次調用select都要重置這三個參數 poll統一處理所有事件類型,因此只需一個事件集參數,用戶通過pollfd.events傳入感興趣的事件,內核通過修改pollfd.revents反饋其中就緒事件 內核通過一個事件表直接管理用戶感興趣的所有事件,因此每次調用epoll_wait時,無需反復傳入用戶感興趣的時間。epoll_wait系統調用的參數events僅用來反饋就緒的事件
應用程序索引就緒文件描述符的時間復雜度 O(n) O(n) O(1)
最大支持的文件描述符數 1024 65535 65535
工作模式 LT LT LT和ET
內核實現和國祚效率 采用輪詢方式來檢測就緒事件,算法時間復雜度為O(n) 采用輪詢方式來檢測就緒事件,算法時間復雜度為O(n) 采用回調方式來檢測就緒事件,時間復雜度O(1)

select、poll、epoll的區別