select和pselect學習筆記

2021-10-10 09:53:18 字數 4953 閱讀 6374

select、pselect用於同步i/o多路復用。select、pselect允許程式同時監聽多個fd,直到其中乙個或多個fd上有對應的i/o操作就緒時,或超時時才返回。

/* fd_set for select and pselect.  */

typedef

struct

fd_set;

fd_set採用bitset方式來儲存設定的fd,這種方式在有效fd數量較少時存在較大的浪費。fd_set有最大連線數限制,即最大連線數為__fd_setsize。如果fd的值太大則會出現陣列記憶體溢位的風險。

struct timeval 

;

struct timespec 

;

輔助巨集函式有fd_clr/fd_isset/fd_set/fd_zero,這些巨集函式主要是用於對fd_set的成員__fds_bits進行bitset操作。巨集函式的詳細定義見標頭檔案:/usr/include/sys/select.h和/usr/include/bits/select.h。

void

fd_clr

(int fd, fd_set *set)

;

從集合set中刪除fd

int

fd_isset

(int fd, fd_set *set)

;

判斷集合set中是否已經設定了fd

void

fd_set

(int fd, fd_set *set)

;

將fd新增到集合set中

void

fd_zero

(fd_set *set)

;

清空整個集合set

posix.1-2001之後

/* according to posix.1-2001 */

#include

早期版本

/* according to earlier standards */

#include

#include

#include

int

select

(int nfds, fd_set *readfds, fd_set *writefds,

fd_set *exceptfds,

struct timeval *timeout)

;

允許程式同時監聽多個fd的i/o事件是否就緒,當乙個或多個fd上有i/o事件就緒時則返回,否則會等到超時後才返回。

引數說明

nfds:nfds的值等於readfds、writefds、exceptfds三個集合中編號最高的fd的值再+1。

readfds:輸入監聽的所有讀事件的fd集合,輸出觸發了讀事件的所有fd集合。輸出fd集合是輸入fd集合的子集。

writefds:輸入監聽的所有寫事件的fd集合,輸出觸發了寫事件的所有fd集合。輸出fd集合是輸入fd集合的子集。

exceptfds:輸入監聽的所有異常事件的fd集合,輸出觸發了異常事件的所有fd集合。輸出fd集合是輸入fd集合的子集。

timeout:select等待超時時間。如果傳入null,則阻塞等待,直到有對應的事件發生才返回;否則最多等待timeout指定的超時時間。

返回值說明

成功返回大於等於0,返回大於0表示三個fd集合中觸發事件的fd的總個數,等於0表示等待超時;錯誤返回-1,錯誤碼從errno中獲取。

錯誤碼說明

ebadf:某個fd集合中新增了無效的fd。

eintr:被訊號中斷。

einval:引數非法。nfds小於0,或timeout是無效的。

enomem:記憶體不足錯誤,導致沒有記憶體用於select內部使用。

說明:對集合readfds、writefds、exceptfds的所有操作必須使用巨集函式fd_clr、fd_isset、fd_set、fd_zero。

檢查當前系統中的glibc庫是否支援pselect介面的方法是檢查對應的巨集_posix_c_source或_xopen_source的值。具體示例**如下:

#if _posix_c_source >= 200112l || _xopen_source >= 600

/* can use pselect */

#else

/* can't use pselect */

#endif

#include

int

pselect

(int nfds, fd_set *readfds, fd_set *writefds,

fd_set *exceptfds,

const

struct timespec *timeout,

const sigset_t *sigmask)

;

允許程式同時監聽多個fd的i/o事件是否就緒,當乙個或多個fd上有i/o事件就緒時則返回,否則會等到超時後才返回。

引數說明

nfds:nfds的值等於readfds、writefds、exceptfds三個集合中編號最高的fd的值再+1。

readfds:輸入監聽的所有讀事件的fd集合,輸出觸發了讀事件的所有fd集合。輸出fd集合是輸入fd集合的子集。

writefds:輸入監聽的所有寫事件的fd集合,輸出觸發了寫事件的所有fd集合。輸出fd集合是輸入fd集合的子集。

exceptfds:輸入監聽的所有異常事件的fd集合,輸出觸發了異常事件的所有fd集合。輸出fd集合是輸入fd集合的子集。

timeout:select等待超時時間。如果傳入null,則阻塞等待,直到有對應的事件發生才返回;否則最多等待timeout指定的超時時間。

sigmask:指向乙個設定了訊號掩碼資訊的結構。如果不為null,則pselect先將當前的訊號掩碼替換成sigmask指向的訊號掩碼,再執行select,最後再替換會原來的訊號掩碼。

返回值說明

成功返回大於等於0,返回大於0表示三個fd集合中觸發事件的fd的總個數,等於0表示等待超時;錯誤返回-1,錯誤碼從errno中獲取。

錯誤碼說明

ebadf:某個fd集合中新增了無效的fd。

eintr:被訊號中斷。

einval:引數非法。nfds小於0,或timeout是無效的。

enomem:記憶體不足錯誤,導致沒有記憶體用於select內部使用。

說明:對集合readfds、writefds、exceptfds的所有操作必須使用巨集函式fd_clr、fd_isset、fd_set、fd_zero。

對pselect的支援對系統和glibc庫有要求,所以使用是必須進行對應編譯巨集檢查,必須要_posix_c_source>=200112l或_xopen_source>=600時才能使用。select則沒有這些限制。

select的timeout引數使用的是struct timeval,精度為微秒。pselect的timeout引數使用的是struct

timespec,精度為納秒。看似pselect超時精度更高,但由於其底層實現是復用的select,所以最後還是會轉換成struct timeval,所以其精度是一樣的。

select返回時會修改timeout的值為其剩餘時間,從而可以得到一次select所消耗的時間。pselect返回時不會修改timeout的值。

pselect有sigmask引數,而select沒有。

所在標頭檔案

#include

struct timeval 

;

struct timespec 

;

#include

#include

#include

#include

#include

#include

intmain

(void)}

else

printf

("no data within five seconds.\n");

exit

(exit_success)

;}

#include

#include

#include

#include

#include

#include

intmain

(void)}

else

printf

("no data within five seconds.\n");

exit

(exit_success)

;}

winsock i o的select模型的學習

include include include pragma comment lib,ws2 32.lib bool insertsock socket psock,socket sock if nindex fd setsize 1 return false return true int mai...

阻塞函式和select

阻塞方式 block,顧名思義,就是程序或是執行緒執行到這些函式時必須等待某個事件發生,如果事件沒有發生,程序或執行緒就被阻塞,函式不能立即返回。非阻塞方式 non block,就是程序或執行緒執行此函式時不必非要等待事件的發生,一旦執行肯定返回,以返回值的不同來反映函式的執 況。如果事件發生則與阻...

for和select迴圈語句

第一種for迴圈語句 for 變數名 in 變數取值列表 do 指令 done 第二種for迴圈語句 for exp1 exp2 exp3 do 指令done 範例 for和while迴圈的對比 for迴圈 for i 1 i 3 i do echo i done while迴圈 i 1while ...