select和poll的用法

2021-05-24 07:42:57 字數 2683 閱讀 8146

select()函式的作用

系統呼叫select和poll的後端實現,用這兩個系統呼叫來查詢裝置是否可讀寫,或是否處於某種狀態。如果poll為空,則驅動裝置會被認為即可讀又可寫,返回值是乙個狀態掩碼

如何使用select()函式?

select()函式的介面主要是建立在一種叫'fd_set'型別的基礎上。它('fd_set') 是一組檔案描述符(fd)的集合。由於fd_set型別的長度在不同平台上不同,因此應該用一組標準的巨集定義來處理此類變數:

fd_set set;

fd_zero(&set);       /* 將set清零 */

fd_set(fd, &set);    /* 將fd加入set */

fd_clr(fd, &set);    /* 將fd從set中清除 */

fd_isset(fd, &set);  /* 如果fd在set中則真 */

在 過去,乙個fd_set通常只能包含少於等於32個檔案描述符,因為fd_set其實只用了乙個int的位元向量來實現,在大多數情況下,檢查 fd_set能包括任意值的檔案描述符是系統的責任,但確定你的fd_set到底能放多少有時你應該檢查/修改巨集fd_setsize的值。*這個值是系 統相關的*,同時檢查你的系統中的select() 的man手冊。有一些系統對多於1024個檔案描述符的支援有問題。[譯者注: linux就是這樣的系統!你會發現sizeof(fd_set)的結果是128(*8 = fd_setsize=1024) 儘管很少你會遇到這種情況。]

select的基本介面十分簡單:

int select(int nfds, fd_set *readset, fd_set *writeset,

fd_set *exceptset, struct timeval *timeout);

其中:

nfds     

需要檢查的檔案描述符個數,數值應該比是三組fd_set中最大數

更大,而不是實際檔案描述符的總數。

readset   

用來檢查可讀性的一組檔案描述符。

writeset

用來檢查可寫性的一組檔案描述符。

exceptset

用來檢查意外狀態的檔案描述符。(注:錯誤並不是意外狀態)

timeout

null指標代表無限等待,否則是指向timeval結構的指標,代表最

長等待時間。(如果其中tv_sec和tv_usec都等於0, 則檔案描述符

的狀態不被影響,但函式並不掛起)

函式將返回響應操作的對應操作檔案描述符的總數,且三組資料均在恰當位置被修改,只有響應操作的那一些沒有修改。接著應該用fd_isset巨集來查詢返回的檔案描述符組。

這裡是乙個簡單的測試單個檔案描述符可讀性的例子:

int isready(int fd)

當然如果我們把null指標作為fd_set傳入的話,這就表示我們對這種操作的發生不感興趣,但select() 還是會等待直到其發生或者超過等待時間。

[譯 者注:在linux中,timeout指的是程式在非sleep狀態中度過的時間,而不是實際上過去的時間,這就會引起和非linux平台移植上的時間不 等問題。移植問題還包括在system v風格中select()在函式退出前會把timeout設為未定義的 null狀態,而在bsd中則不是這樣, linux在這點上遵從system v,因此在重複利用timeout指標問題上也應該注意。]

linux下select呼叫的過程:

1.使用者層應用程式呼叫select(),底層呼叫poll())

2.核心層呼叫sys_select() ------> do_select()

最終呼叫檔案描述符fd對應的struct file型別變數的struct file_operations *f_op的poll函式。

poll指向的函式返回當前可否讀寫的資訊。

1)如果當前可讀寫,返回讀寫資訊。

2)如果當前不可讀寫,則阻塞程序,並等待驅動程式喚醒,重新呼叫poll函式,或超時返回。

3.驅動需要實現poll函式。

當驅動發現有資料可以讀寫時,通知核心層,核心層重新呼叫poll指向的函式查詢資訊。

poll_wait(filp,&wait_q,wait)    // 此處將當前程序加入到等待佇列中,但並不阻塞

在中斷中使用wake_up_interruptible(&wait_q)喚醒等待佇列。 另:

select的本質是採用32個整數的32位,即32*32= 1024來標識,fd值為1-1024。當fd的值超過1024限制時,就必須修改fd_setsize的大小。這個時候就可以標識32*max值範圍的fd。

對於單程序多執行緒,每個執行緒處理多個fd的情況,select是不適合的。

1.所有的執行緒均是從1-32*max進行掃瞄,每個執行緒處理的均是一段fd值,這樣做有點浪費

2.1024上限問題,乙個處理多個使用者的程序,fd值遠遠大於1024

所以這個時候應該採用poll,poll傳遞的是陣列頭指標和該陣列的長度,只要陣列的長度不是很長,效能還是很不錯的,因為poll一次在核心中申請4k(乙個頁的大小來存放fd),盡量控制在4k以內

至於epoll還是poll的一種優化,返回後不需要對所有的fd進行遍歷,在核心中維持了fd的列表。select和poll是將這個核心列表維持在使用者態,然後傳遞到核心中。但是只有在2.6的核心才支援。

epoll更適合於處理大量的fd ,且活躍fd不是很多的情況,畢竟fd較多還是乙個序列的操作.

linux下select和poll的用法

select 函式的作用 系統呼叫select和poll的後端實現,用這兩個系統呼叫來查詢裝置是否可讀寫,或是否處於某種狀態。如果poll為空,則驅動裝置會被認為即可讀又可寫,返回值是乙個狀態掩碼 如何使用select 函式?select 函式的介面主要是建立在一種叫 fd set 型別的基礎上。它...

Linux下select和poll的用法

select 函式的作用 系統呼叫select和poll的後端實現,用這兩個系統呼叫來查詢裝置是否可讀寫,或是否處於某種狀態。如果poll為空,則驅動裝置會被認為即可讀又可寫,返回值是乙個狀態掩碼 如何使用select 函式?select 函式的介面主要是建立在一種叫 fd set 型別的基礎上。它...

poll 和select 使用總結

poll poll函式和select函式功能十分相似,函式宣告 int poll struct pollfd fds,nfds t nfds,int timeout 引數說明 fds 是乙個struct pollfd結構型別的陣列 用於存放需要檢測其狀態的socket描述符 每當 呼叫這個函式之後,...