select函式的使用

2021-06-05 04:56:55 字數 4483 閱讀 8824

select

函式:系統提供

select

函式來實現多路復用輸入

/輸出模型。原型:

#include sys/time.h>

#include unistd.h>

select

函式:系統提供

select

函式來實現多路復用輸入

/輸出模型。原型:

#include sys/time.h>

#include unistd.h>

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

引數maxfd

是需要監視的最大的檔案描述符值+1;

rdset,wrset,exset

分別對應於需要檢測的可讀檔案描述符的集合,可寫檔案描述符的集

合及異常檔案描述符的集合。

struct timeval

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

fd_zero,fd_set,fd_clr,fd_isset:

fd_zero(fd_set *fdset);

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

fd_set(fd_set *fdset);

用於在檔案描述符集合中增加乙個新的檔案描述符。

fd_clr(fd_set *fdset);

用於在檔案描述符集合中刪除乙個檔案描述符。

fd_isset(int fd,fd_set *fdset);

用於測試指定的檔案描述符是否在該集合中。

struct timeval

結構:struct timeval

timeout

設定情況:

null:select

將一直被阻塞,直到某個檔案描述符上發生了事件。

0:僅檢測描述符集合的狀態,然後立即返回,並不等待外部事件的發生。

特定的時間值:如果在指定的時間段裡沒有事件發生,

select

將超時返回。--(

'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

個檔案描述符的支援有問題。

多路復用的方式是真正實用的伺服器程式,非多路復用的網路程式只能作為學習或著陪測的角色。本文說下個人

接觸過的多路復用函式:

select/poll/epoll/port

。kqueue

的*nix

系統沒接觸過,估計熟悉了上面

四種,kqueue

也只是需要熟悉一下而已。

一、select

模型select

原型:int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

其中引數

n表示監控的所有

fd中最大值+1。

和select

模型緊密結合的四個巨集,含義不解釋了:

fd_clr(int fd, fd_set *set);

fd_isset(int fd, fd_set *set);

fd_set(int fd, fd_set *set);

fd_zero(fd_set *set);

理解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)

的值。我這邊服務

器上sizeof(fd_set)

=512

,每bit

表示乙個檔案描述符,則我伺服器上支援的最大檔案描述符是

512*8=4096

。據說可調,另有說雖

然可調,但調整上限受於編譯核心時的變數值。本人對調整

fd_set

的大小不太感興趣,參考

/cppexplore/archive/2008/03/21/45061.html

中的模型2(

1)可以有效突破

select

可監控的檔案描述符上限。(

2)將fd加入

select

監控集的同時,還要再使用乙個資料結構

array

儲存放到

select

監控集中的

fd,一是用於再

select

返回後,

array

作為源資料和

fd_set

進行fd_isset

判斷。二是

select

返回後會把以前加入的但並無事件發生的

fd清空,則每次開始

select

前都要重新從

array

取得fd

逐一加入(

fd_zero

最先),掃瞄

array

的同時取得

fd最大值

maxfd

,用於select

的第乙個

引數。(

3)可見

select

模型必須在

select

前迴圈array

(加fd

,取maxfd

),select

返回後迴圈

array

(fd_isset

判斷是否有時間發生)。

下面給乙個偽碼說明基本

select

模型的伺服器模型:

array[slect_len];

nsock=0;

array[nsock++]=listen_fd;(

之前listen port

已繫結並

listen)

maxfd=listen_fd;

while

res=select(maxfd+1,&set,0,0,0)

;if(fd_isset(listen_fd,&set))

foreach 下標1

開始(fd in array)

}

select函式的使用

select函式是 i o 復用中非常重要的乙個函式,屬於併發程式設計的。它能夠監視我們需要監視的檔案描述符的變化情況 讀 寫或者異常 include select.h intselect int maxfdp,fd set readfds,fd set writefds,fd set errorf...

select 函式 使用

告知核心等待某一或某些事件發生 而後喚醒程序 或超時返回 int select int maxfdp1,fd set readset,fd set writeset,fd set excepset,const struct timeval timeout 返回準備好的描述符數量 超時返0錯誤 1 主...

select函式使用

這兩天寫了這麼一段 select直接返回 1,錯誤資訊是 invalid argments 顯然沒有達到阻塞超時的效果。如下 bool issocketwaitread inf fd,int usec 這段 在標準的linux環境可以執行,但是在arm體系架構的國產化作業系統下,返回值永遠是 1 修...