對於多個非阻塞i/o,怎麼知道i/o何時已經處於可讀或可寫狀態?
如果採用迴圈一直呼叫write/read,直到返回成功,這樣的方式成為輪詢(polling)。大多數時間i/o沒有處於就緒狀態,因此這樣的輪詢十分浪費cpu。
一種比較好的技術是使用i/o多路轉接,也叫做i/o多路復用。其基本思想為:先構造乙個有關描述符的列表,然後呼叫乙個函式,直到這些描述符中的乙個已經準備好進行i/o時,該函式才返回。在返回時,它告訴程序哪些描述符已經準備好可以進行i/o了。
有3個函式poll、pselect、select可以使我們能夠執行i/o多路轉接。posix標準定義了select函式,poll是對該基本部分的xsi擴充套件。
select和pselect函式
select函式的引數告訴核心
1、我們所關心的描述符
2、對於每個描述符我們所關心的狀態(是否讀/寫乙個給定的描述符?是否關心乙個描述符的異常狀態?)
3、願意等待多長時間(可以永遠等待、等待乙個固定時間、或不等待)
4、已經準備好描述符的狀態
5、對於讀、寫或異常這三個狀態中的每乙個,哪些描述符已經準備好
當使用select的返回資訊時,就可以呼叫相應的i/o函式(例如read或write),並且確知該函式不會阻塞。函式原型:
#include
int select(int maxfdp1, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict tvptr)
返回值:準備就緒的描述符數,若超時則返回0,若出錯則返回-1
struct timeval;
當tvptr=null時,永遠等待。如果捕捉到乙個訊號則中斷此無限等待。
當tvptr->tv_sec=0且tvptr->tv_usec=0時,完全不等待。
當tvptr->tv_sec!=0或tvptr->tv_usec!=0時,等待相應時間。當指定描述符之一準備好時,或當指定時間已經超時,返回。
中間三個引數readfds、writefds、exceptfds指向描述符集的指標,是我們關心的可讀、可寫、處於異常條件的各個描述符。每個描述符集存放在fd_set資料型別中。這種資料型別為每一可能的描述符保持了一位,如圖:
第乙個引數maxfdp1的意思是最大描述符加1。在三個描述符集中找到最大描述符對應的數值加1。表示核心在此範圍內尋找開啟的位。
posix.1定義了乙個select的變體pselect,原型如下:
int pselect(int maxfd1, fd_set *restrict readfds, fd_set *restrict writefds,
fd_set *restrict exceptfds, const struct timespec *restrict timeout,
const sigset_t *restrict sigmask)
和select有以下幾點區別:
1、pselect超時值用的資料結構為timespec,更為準確
2、pselect超時值宣告為const,保證了在pselect函式中不會改變
3、pselect可以指定乙個訊號遮蔽字,在呼叫時,以原子操作的方式安裝該訊號遮蔽字,在返回時恢復以前的訊號遮蔽字。
poll函式
poll類似select函式,原型如下:
#include
int poll(struct pollfd fdarray, nfds_t nfds, int timeout)
poll沒有為每個狀態(可讀、可寫、異常)構造乙個描述符集,而是構造了乙個pollfd結構體陣列,每個陣列指定乙個描述符編號以及對其關心的狀態。
struct pollfd ;
應該events事件設定成下表所表示的值,告訴核心我們關心的是什麼。返回時,核心設定revents說明該描述符發生了什麼。
最後乙個引數說明願意等待的時間。
I O多路轉接
include include include include include include include include include include include 巨集定義埠號 define portnumber 8000 define max line 80 int main void...
I O多路轉接(select
一.基本概念 二.函式原型 includeint select int nfds,fd set readfds,fd set writefds,fd set exceptions,struct timeval timeout fd set 介面 void fd clr int fd,fd set s...
select多路IO轉接
void fd zero fd set set 清空乙個檔案描述符集合。fd set rset fd zero rset void fd set int fd,fd set set 將待監聽的檔案描述符,新增到監聽集合中 fd set 3,rset fd set 5,rset fd set 6,rs...