select poll epoll的一些知識

2022-08-31 16:06:19 字數 4620 閱讀 4641

i/o復用使的程式能同時監聽多個檔案

描述符,這對提

高程式的效能至關重要。通常網路程式在下列情況下需要使用i/o復用技術:

(1)客戶端程式要同時處理多個socket

(2)客戶端程式要同時處理使用者輸入和網路連線

(3)tcp伺服器要同時處理監聽socket和連線socket(這時i/o復用使用最多的場合)

(4)伺服器要同時處理tcp請求和udp請求

(5)伺服器要同時監聽多個埠,或者處理多種服務。

需要指出的是,i/o復用雖然能同時監聽多個檔案描述符,但是它本身是阻塞的。並且當多個檔案描述符就緒時,如果不採取額外的措施,程式就只能按順序依次處理其中的每乙個檔案描述符,這使得伺服器程式看起來像是序列工作。如果要實時併發,只能使用多程序和多執行緒等手段。

2、select函式

1#include select

.h>  

2int

select

(int

nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 

struct

timeval *timeout)  

返回值:select成功時返回就緒檔案描述符的總數,超時沒有人任何檔案描述符準備就緒,返回0.;出錯返回-1

函式引數介紹:

(1)nfds引數指定被監聽的檔案描述符的總數。它通常被設定為監聽的所有檔案描述符加一,因為檔案描述符是從0開始計數的。

(2)readfds、writefds、exceptfds引數分別指向可讀、可寫和異常等事件對應的檔案描述符,應用程式呼叫select函式時,通過這三個引數傳入自己感興趣的檔案描述符。select返回時,核心將修改他們來通知應用程式那些檔案描述符已經就緒。這三個引數都是fd_set結構體指標型別。fd_set結構體僅包含乙個整形陣列,該陣列的每乙個元素的每一位標記乙個檔案描述符,fd_set所能容納的檔案描述符有fd_setsize指定,這就限制了select能同時處理的檔案描述符的總量。可以通過下面的巨集來訪問fd_set結構體中的位

1 #include select.h>  

2 fd_zero(fd_set *fdset)              //

清除fdset的所有位  

3fd_set(int fd,  fd_set *fd_set)        //

設定fdset的位fd  

4fd_clr(int fd,  fd_set *fd_set)         //

清除fdset的位fd  

5fd_isset(

intfd,  fd_set *fd_set)     

//測試fdset的位fd是否被設定  

(3)timeout用來設定select函式的超時時

1 struct timeval  

2 ;  

這個引數有三種可能:當把引數設定為null,則select將一直阻塞,直到某個檔案描述符準備就緒;設定為乙個固定的時間,在有乙個描述符準備好返回,但是不超過指定的時間;設定為0時,select則立即返回。

2、poll函式

poll系統呼叫的select類似,也是在指定時間內輪詢一定數量的檔案描述符,以測試其是否就緒

1 #include 

2 int poll(struct pollfd *fds, nfds_t nfds, int timrout);  

(1)fds引數是乙個pollds型別的結構體陣列,它指定在我們感興趣的檔案描述符上發生可讀、可寫和異常事件。pollfd結構體的定義

1 struct pollfd  

2  ;  

每個結構體的events域是監控該檔案描述符的事件掩碼,由使用者來設定這個域,revents域是檔案描述符的操作結果事件掩碼,核心在呼叫返回時設定這個域。events域中請求的任何事件都可能在revents域中返回。合法的事件如下:

1 pollin         有資料可讀。  

2 pollrdnorm        有普通資料可讀。  

3 pollrdband       有優先資料可讀。  

4 pollpri         有緊迫資料可讀。  

5 pollout            寫資料不會導致阻塞。  

6 pollwrnorm        寫普通資料不會導致阻塞。  

7 pollwrband        寫優先資料不會導致阻塞。  

8 pollmsgsigpoll     訊息可用。  

9 poller               指定的檔案描述符發生錯誤。  

10 pollhup             指定的檔案描述符掛起事件。  

(2)nfds引數指定被監聽事件集合fds的大小

(3)timeout引數指定poll的超時值。當timeout為-1時,poll呼叫將永遠阻塞,直到某個事件發生;當timeout為0時,poll將立即返回。

3、epoll函式

epoll是linux特有的i/o復用函式。它在實際和使用上和select、poll有很大的差異。首先,epoll使用一組函式來完成任務,而不是單個函式。其次,epoll把使用者關心的檔案描述符上的事件放在核心裡的乙個事件表中,從而無需想select和poll那樣每次呼叫都要重複傳入檔案描述符集。但是epoll需要使用乙個額外的檔案描述符,來唯一標識核心中的這個事件表。

(1)這個檔案描述符使用epoll_create函式來建立:

1 #include 

2 int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);  

該函式返回成功就緒檔案描述符的個數,失敗是返回-1並設定errno。

類似於select呼叫。引數events用來從核心得到事件的集合,maxevents的值不能大於建立epoll_create時的size,引數timeout是超時時間

5、lt和et模式

lt模式(水平觸發):當epoll_wait檢測到其上有事件發生並將此事件通知應用程式後,應用程式可以不立即處理該事件。這樣,當應用程式下一次呼叫epoll_wait時,epoll_wait還會再次向應用程式通告次事件。

et模式(邊沿觸發):當epoll_wait檢測到其上有事件發生並將此事件通知應用程式後,應用程式必須立即處理該事件,因為後續的epoll_wait呼叫將不再向應用程式通知這一事件。epoll工作在et模式的時候,必須使用非阻塞套接字,以避免由於乙個檔案控制代碼阻塞讀/阻塞寫操作把處理多個檔案描述符的任務餓死。

可見,et模式在很大程度上降低了同乙個epoll事件被重複觸發的次數,因此效率要比lt模式高。

6、三組i/o復用函式的比較

(1)事件集:

poll:poll的引數pollfd,它把檔案描述符和事件都定義在其中,任何事件都被統一處理,從而使程式設計介面簡單的多,並且核心每次修改的是pollfd結構體的revents成員,而events 成員保持不變,因此下次呼叫poll時應用程式無需重置pollfd型別的事件集合。

epoll:epoll採用完全不同與select和poll的方式來管理使用者註冊的事件。它在核心中維護一張事件表,並提供乙個獨立的系統呼叫epoll_ctl來控制往其中新增、刪除、修改事件。這樣,每次epoll_wait呼叫都直接從核心事件表中取得使用者註冊的事件,而無需反覆從使用者空間讀入這些事件。

(2)最大支援檔案描述符數:

select:select開啟的檔案描述符fd是由一定限制的,有 fd_size設定,預設為2048,對於那些需要支援上萬連線數目的伺服器來說顯然太少了。

poll和epoll:poll和epoll分別用nfds和maxevents引數指定最多監聽多少個檔案描述符和事件,這兩個值都能達到系統允許開啟的最大檔案描述符數目,即65535。

(3)工作模式:

select和poll都只能工作在相對低效的lt模式,而epoll則可以工作在et高效模式。

(4)實現原理:

select和poll採用的都是輪詢的方式,即每次呼叫都要掃瞄整個註冊檔案描述符集合,並將其中就緒的檔案描述符返回給使用者,因此他們檢測就緒事件的演算法時間複雜度是o(n)。

epoll的epoll_wait則不同,它採用的是**函式的方式。核心檢測到就緒的檔案描述符時,將觸發**函式,**函式就將該檔案描述符上對應的時間插入核心就緒事件佇列。核心最後在適當的時候將就緒事件佇列中的內容拷貝到使用者空間。因此epoll_wait無需輪詢整個檔案描述符集合來檢測那些事件已經準備就緒,其演算法事件複雜度o(1)。但是,當活動鏈結比較多時,epoll_wait的效率未必比select和poll高,因為**函式被觸發得過於頻繁。所以epoll_wait適用於連線數量多,但是活動連線少的情況。

(5)使用mmap加速核心與使用者空間的訊息傳遞。

這點實際上涉及到epoll的具體實現了。無論是select,poll還是epoll都需要核心把fd訊息通知給使用者空間,如何避免不必要的記憶體拷貝就很重要,在這點上,epoll是通過核心於使用者空間mmap同一塊記憶體實現的。

select poll epoll學習筆記

io多路復用,網路程式設計。io模型 阻塞式io模型 非阻塞式io模型,需要輪詢核心,較少使用 io復用模型,阻塞於select 訊號驅動式io模型 核心通知使用者程序何時可以啟動乙個io操作 非同步io模型 核心通知使用者程序操作何時完成。posix標準 可移植作業系統介面,ieee為各種在uni...

select poll epoll事件驅動

一直用select,沒有使用poll和epoll,近來需要使用epoll。以前面試時,有人問過我,我也簡單作答。現在寫一下我的理解。三者區別 select 監聽的檔案描述符有限制,linux系統預設是1024 poll 和select差不多,比select優越的地方是監聽的檔案描述符個數可以不限 e...

select poll epoll模型對比

select poll epoll模型對比 先說select 1.socket數量限制 該模式可操作的socket數由fd setsize決定,核心預設32 32 1024.2.操作限制 通過遍歷fd setsize個socket來完成排程,不管哪個socket是活躍的,都遍歷一遍.後說poll 1...