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 修...