select函式的用法

2021-09-29 08:25:10 字數 2711 閱讀 8418

select函式用於在非阻塞中,當乙個套接字或一組套接字有訊號時通知你,系統提供select函式來實現多路復用輸入/輸出模型,原型:

int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout);

所在的標頭檔案為:#include 和#include

先對函式中的引數做乙個簡單的介紹。引數maxfd是需要監視的最大的檔案描述符值+1;rdset,wrset,exset分別對應於需要檢測的可讀檔案描述符的集合,可寫檔案描述符的集 合及異常檔案描述符的集合。struct timeval結構用於描述一段時間長度,如果在這個時間內,需要監視的描述符沒有事件發生則函式返回,返回值為0。

在這些引數中有乙個類似於結構體的東西,fd_set,這是什麼的名字,我們先來看看這個所具有的含義吧。這是一組檔案描述字(fd)的集合,它用一位來表示乙個fd,等等,檔案描述字,熟悉吧,之前都把這個當做乙個檔案的路徑儲存的地方了,也就是當做是乙個檔案的標誌哦,現不在做猜想了,看看下文是怎麼介紹的吧。

對於fd_set型別通過下面四個巨集來操作:

fd_zero(fd_set *fdset) 將指定的檔案描述符集清空,在對檔案描述符集合進行設定前,必須對其進行初始化,如果不清空,由於在系統分配記憶體空間後,通常並不作清空處理,所以結果是不可知的。

fd_set(fd_set *fdset) 用於在檔案描述符集合中增加乙個新的檔案描述符。

fd_clr(fd_set *fdset) 用於在檔案描述符集合中刪除乙個檔案描述符。

fd_isset(int fd,fd_set *fdset) 用於測試指定的檔案描述符是否在該集合中。

過去。。。。。。好長一大段哦,為了保證大家的注意力,我決定將這一大段長長的對過去情況的介紹去掉,直接尋找正題,保持目標的關注度啊。現在,unix系統通常會在標頭檔案中定義常量fd_setsize,它是資料型別fd_set的描述字數量,其值通常是1024,這樣就能表示<1024的fd。

好了在研究了一番關於fd_set的資訊之後,再回到對select函式的理解上來吧。

功能:測試指定的fd可讀?可寫?有異常條件待處理?

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

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

exceptset用來檢查是否有異常條件出現的檔案描述字。(注:不包括錯誤)

timeout 用於描述一段時間長度,如果在這個時間內,需要監視的描述符沒有事件發生則函式返回,返回值為0。

對於select函式的功能簡單的說就是對檔案fd做乙個測試。測試結果有三種可能:

1.timeout=null(阻塞:select將一直被阻塞,直到某個檔案描述符上發生了事件)

3.timeout所指向的結構,時間設為0(非阻塞:僅檢測描述符集合的狀態,然後立即返回,並不等待外部事件的發生)

返回值:返回對應位仍然為1的fd的總數。注意啦:只有那些可讀,可寫以及有異常條件待處理的fd位仍然為1。否則為0哦。舉個例子,比如recv(), 在沒有資料到來呼叫它的時候,你的執行緒將被阻塞,如果資料一直不來,你的執行緒就要阻塞很久.這樣顯然不好。所以採用select來檢視套節字是否可讀(也就是是否有資料讀了) 。

步驟如下——

socket s;

.....

fd_set set;

while(1)

//do something here

}

理解select模型的關鍵在於理解fd_set,為說明方便,取fd_set長度為1位元組,fd_set中的每一bit可以對應乙個檔案描述符fd。則1位元組長的fd_set最大可以對應8個fd。
(1)執行fd_set set; fd_zero(&set);則set用位表示是0000,0000。

(2)若fd=5,執行fd_set(fd,&set);後set變為0001,0000(第5位置為1)

(3)若再加入fd=2,fd=1,則set變為0001,0011

(4)執行select(6,&set,0,0,0)阻塞等待

(5)若fd=1,fd=2上都發生可讀事件,則select返回,此時set變為0000,0011。注意:沒有事件發生的fd=5被清空。

基於上面的討論,可以輕鬆得出select模型的特點:

(1)可監控的檔案描述符個數取決與sizeof(fd_set)的值。

(2)可以有效突破select可監控的檔案描述符上限。

(3)將fd加入select監控集的同時,還要再使用乙個資料結構array儲存放到select監控集中的fd,一是用於再select 返回後,array作為源資料和fd_set進行fd_isset判斷。二是select返回後會把以前加入的但並無事件發生的fd清空,則每次開始 select前都要重新從array取得fd逐一加入(fd_zero最先),掃瞄array的同時取得fd最大值maxfd,用於select的第乙個 引數。

(4)可見select模型必須在select前迴圈array(加fd,取maxfd),select返回後迴圈array(fd_isset判斷是否有時間發生)。

使用select函式的過程一般是:

先呼叫巨集fd_zero將指定的fd_set清零,然後呼叫巨集fd_set將需要測試的fd加入fd_set,接著呼叫函式select測試fd_set中的所有fd,最後用巨集fd_isset檢查某個fd在函式select呼叫後,相應位是否仍然為1。

以下是乙個測試單個檔案描述字可讀性的例子:

int isready(int fd)

select函式用法

原型 int select intnfds fd set readfds fd set writefds fd set exceptfds const struct timeval timeout nfds 本引數忽略,僅起到相容作用。readfds 可選 指標,指向一組等待可讀性檢查的套介面。wr...

Select函式用法

select函式用於在非阻塞中,當乙個套接字或一組套接字有訊號時通知你,系統提供select函式來實現多路復用輸入 輸出模型,原型 include include int select int maxfd,fd set rdset,fd set wrset,fd set exset,struct t...

fd set 用法 select函式相關

select 函式主要是建立在fd set型別的基礎上的。fd set 它比較重要所以先介紹一下 是一組檔案描述字 fd 的集合,它用一位來表示乙個fd 下面會仔細介紹 對於fd set型別通過下面四個巨集來操作 fd set set fd zero set fd set fd,set fd clr...