linux—select詳解(轉載)

轉載

<!--@page { margin: 2cm }P { margin-bottom: 0.21cm }-->

select系統調用時用來讓我們的程序監視多個文件句柄的狀態變化的。程序會停在select這裏等待,直到被監視的文件句柄有一個或多個發生了狀態改變。

關於文件句柄,其實就是一個整數,通過socket函數的聲明就明白了:

int socket(int domain, int type, intprotocol);

我們最熟悉的句柄是0、1、2三個,0是標準輸入,1是標準輸出,2是標準錯誤輸出。0、1、2是整數表示的,對應的FILE*結構的表示就是stdin、stdout、stderr。


繼續上面的select,就是用來監視某個或某些句柄的狀態變化的。select函數原型如下:

int select (int nfds, fd_set *readfds,fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

函數的最後一個參數timeout是一個超時時間值。其類型是structtimeval *,即一個structtimeval結構的變量的指針,所以我們在程序裏要聲明一個structtimeval tv;然後把變量tv的地址&tv傳遞給select函數。structtimeval結構如下:

struct timeval

{

longtv_sec; //seconds

longtv_usec; //microseconds

};

第2、3、4三個參數是一樣的類型;fd_set*,即我們在程序裏要申請幾個fd_set類型的變量,比如rdfds,wtfds,exfds,然後把這個變量的地址&rdfds,&wtfds,&exfds傳遞給select函數。這三個參數都是一個句柄的集合,第一個rdfds是用來保存這樣的句柄的:當句柄的狀態變成可讀時系統就告訴select函數返回,同理第二個函數是指向有句柄狀態變成可寫時系統就會告訴select函數返回,同理第三個參數exfds是特殊情況,即句柄上有特殊情況發生時系統會告訴select函數返回。特殊情況比如對方通過一個socket句柄發來了緊急數據。如果我們程序裏只想檢測某個socket是否有數據可讀http://www.czjiny.com/,我們可以這樣:

fd_set rdfds;

struct timeval tv;

intret;

FD_ZERO(&rdfds);

FD_SET(socket, &rdfds);

tv.tv_sec = 1;

tv.tv_uses = 500;

ret = select (socket + 1, %rdfds,NULL, NULL, &tv);

if(ret < 0) p

MFC製作程序界面鎖定

error (“select”);

else if (ret = = 0) printf(“timeout”);

else {

printf(“ret= %d/n”,ret);

if(FD_ISSET(socket,&rdfds)){

 

recv( );

}

}

注意select函數的第一個參數,是所有加入集合的句柄值的最大那個那個值還要加1.比如我們創建了3個句柄;

int sa, sb, sc;

sa = socket(……);

connect (sa,….);

 

sb = socket(….);

connect (sb,…);

 

sc = socket(….);

connect(sc,…);

 

FD_SET(sa, &rdfds);

FD_SET(sb, &rdfds);

FD_SET(sc, &rdfds);

 

在使用select函數之前,一定要找到3個句柄中的最大值是哪個,我們一般定義一個變量來保存最大值,取得最大socket值如下:

int maxfd = 0;

if(sa > maxfd) maxfd = sa;

if(sb > maxfd) maxfd = sb;

if(sc > maxfd) maxfd = sc;

 

然後調用select函數:

ret = select (maxfd+1, &rdfds,NULL, NULL,&tv);

 

同樣的道理,如果我們是檢測用戶是否按了鍵盤進行輸入,我們就應該把標準輸入0這個句柄放到select裏來檢測,如下:

FD_ZERO(&rdfds);

FD_SET(0, &rdfds);

tv.tv_sec = 1;

tv.tv_usec = 0;

ret = select (1,&rdfds,NULL,NULL,&tv);

if(ret < 0) perror(“select”);

else if (ret = = 0) printf (“timeout/n”);

else{

scanf(“%s”,buf);

}

發佈了109 篇原創文章 · 獲贊 5 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章