日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

select函數(shù)詳細(xì)介紹

 杰出天下 2011-04-25

select函數(shù)

簡(jiǎn)介:這是select函數(shù)的詳細(xì)頁(yè)面,介紹了和linux,有關(guān)的知識(shí)、技巧、經(jīng)驗(yàn),和一些linux源碼等。

select

(1)select函數(shù)說(shuō)明

前面的fcntl函數(shù)解決了文件的共享問(wèn)題,接下來(lái)該處理I/O 復(fù)用的情況了。

總的來(lái)說(shuō),I/O 處理的模型有5 種。

· 阻塞 I/O模型在這種模型下,若所調(diào)用的I/O 函數(shù)沒(méi)有完成相關(guān)的功能就會(huì)使進(jìn)程

掛起,直到相關(guān)數(shù)據(jù)到才會(huì)出錯(cuò)返回。如常見(jiàn)對(duì)管道設(shè)備、終端設(shè)備和網(wǎng)絡(luò)設(shè)備進(jìn)行讀寫(xiě)時(shí)

經(jīng)常會(huì)出現(xiàn)這種情況。

· 非阻塞模型:在這種模型下,當(dāng)請(qǐng)求的I/O 操作不能完成時(shí),則不讓進(jìn)程睡眠,

而且返回一個(gè)錯(cuò)誤。非阻塞I/O 使用戶可以調(diào)用不會(huì)永遠(yuǎn)阻塞的I/O 操作,如open、write

和read。如果該操作不能完成,則會(huì)立即出錯(cuò)返回,且表示該I/O 如果該操作繼續(xù)執(zhí)行

就會(huì)阻塞。

· I/O多路轉(zhuǎn)接模型:在這種模型下,如果請(qǐng)求的I/O操作阻塞,且它不是真正阻塞I/O,

而是讓其中的一個(gè)函數(shù)等待,在這期間,I/O 還能進(jìn)行其他操作。如本節(jié)要介紹的select函數(shù)

和poll函數(shù),就是屬于這種模型。

· 信號(hào)驅(qū)動(dòng) I/O 模型:在這種模型下,通過(guò)安裝一個(gè)信號(hào)處理程序,系統(tǒng)可以自動(dòng)

捕獲特定信號(hào)的到來(lái),從而啟動(dòng)I/O。這是由內(nèi)核通知用戶何時(shí)可以啟動(dòng)一個(gè)I/O 操作

決定的。

· 異步 I/O模型:在這種模型下,當(dāng)一個(gè)描述符已準(zhǔn)備好,可以啟動(dòng)I/O 時(shí),進(jìn)程會(huì)通

知內(nèi)核。現(xiàn)在,并不是所有的系統(tǒng)都支持這種模型。

可以看到,select的I/O 多路轉(zhuǎn)接模型是處理I/O 復(fù)用的一個(gè)高效的方法。它可以具體設(shè)

置每一個(gè)所關(guān)心的文件描述符的條件、希望等待的時(shí)間等,從select 函數(shù)返回時(shí),內(nèi)核會(huì)通

知用戶已準(zhǔn)備好的文件描述符的數(shù)量、已準(zhǔn)備好的條件等。通過(guò)使用select 返回值,就可以

調(diào)用相應(yīng)的I/O 處理函數(shù)了。

(2)select函數(shù)格式

Select函數(shù)的語(yǔ)法格式如表6.8 所示。

表6.8 fcntl函數(shù)語(yǔ)法要點(diǎn)

所需頭文件

#include <sys/types.h>

#include <sys/time.h>

#include <unistd.h>

函數(shù)原型int select(int numfds,fd_set *readfds,fd_set *writefds,fd_set *exeptfds,struct timeval

*timeout)

numfds:需要檢查的號(hào)碼最高的文件描述符加1

readfds:由select()監(jiān)視的讀文件描述符集合

writefds:由select()監(jiān)視的寫(xiě)文件描述符集合

exeptfds:由select()監(jiān)視的異常處理文件描述符集合

NULL:永遠(yuǎn)等待,直到捕捉到信號(hào)或文件描述符已準(zhǔn)備好為止

具體值:struct timeval類型的指針,若等待為timeout時(shí)間還沒(méi)有文件描

符準(zhǔn)備好,就立即返回

函數(shù)傳入值

timeout

0:從不等待,測(cè)試所有指定的描述符并立即返回

函數(shù)返回值

成功:準(zhǔn)備好的文件描述符

-1:出錯(cuò)

思考

請(qǐng)讀者考慮一下如何確定最高的文件描述符?

可以看到,select 函數(shù)根據(jù)希望進(jìn)行的文件操作對(duì)文件描述符進(jìn)行了分類處理,這里,

對(duì)文件描述符的處理主要涉及到4 個(gè)宏函數(shù),如表6.9 所示。

表6.9 select文件描述符處理函數(shù)

FD_ZERO(fd_set *set) 清除一個(gè)文件描述符集

FD_SET(int fd,fd_set *set) 將一個(gè)文件描述符加入文件描述符集中

FD_CLR(int fd,fd_set *set) 將一個(gè)文件描述符從文件描述符集中清除

FD_ISSET(int fd,fd_set *set) 測(cè)試該集中的一個(gè)給定位是否有變化

一般來(lái)說(shuō),在使用select 函數(shù)之前,首先使用FD_ZERO 和FD_SET 來(lái)初始化文件描述

符集,在使用了select 函數(shù)時(shí),可循環(huán)使用FD_ISSET 測(cè)試描述符集,在執(zhí)行完對(duì)相關(guān)后文

件描述符后,使用FD_CLR來(lái)清楚描述符集。

另外,select函數(shù)中的timeout是一個(gè)struct timeval類型的指針,該結(jié)構(gòu)體如下所示:

struct timeval {

long tv_sec; /* second */

long tv_unsec; /* and microseconds*/

}

可以看到,這個(gè)時(shí)間結(jié)構(gòu)體的精確度可以設(shè)置到微秒級(jí),這對(duì)于大多數(shù)的應(yīng)用而言已經(jīng)

足夠了。

(3)使用實(shí)例

由于 Select函數(shù)多用于I/O 操作可能會(huì)阻塞的情況下,而對(duì)于可能會(huì)有阻塞I/O 的管道、

網(wǎng)絡(luò)編程,本書(shū)到現(xiàn)在為止還沒(méi)有涉及。因此,本例主要表現(xiàn)了如何使用select 函數(shù),而其

中的I/O 操作是不會(huì)阻塞的。

本實(shí)例中主要實(shí)現(xiàn)將文件hello1 里的內(nèi)容讀出,并將此內(nèi)容每隔10s 寫(xiě)入hello2 中去。

在這里建立了兩個(gè)描述符集,其中一個(gè)描述符集inset1 是用于讀取文件內(nèi)容,另一個(gè)描述符

集inset2是用于寫(xiě)入文件的。兩個(gè)文件描述符fds[0]和fds[1]分別指向這一文件描述符。在首

先初始化完各文件描述符集之后,就開(kāi)始了循環(huán)測(cè)試這兩個(gè)文件描述符是否可讀寫(xiě),由于在

這里沒(méi)有阻塞,所以文件描述符處于準(zhǔn)備就緒的狀態(tài)。這時(shí),就分別對(duì)文件描述符fds[0]和

fsd[1]進(jìn)行讀寫(xiě)操作。該程序的流程圖如圖6.2 所示。

/*select.c*/

#include <fcntl.h>

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <time.h>

int main(void)

{

int fds[2];

char buf[7];

int i,rc,maxfd;

fd_set inset1,inset2;

struct timeval tv;

/*首先按一定的權(quán)限打開(kāi)hello1文件*/

if((fds[0] = open ("hello1", O_RDWR|O_CREAT,0666))<0)

perror("open hello1");

/*再按一定的權(quán)限打開(kāi)hello2文件*/

if((fds[1] = open ("hello2", O_RDWR|O_CREAT,0666))<0)

perror("open hello2");

if((rc = write(fds[0],"Hello!\n",7)))

printf("rc=%d\n",rc);

lseek(fds[0],0,SEEK_SET);

/*取出兩個(gè)文件描述符中的較大者*/

maxfd = fds[0]>fds[1] ? fds[0] : fds[1];

/*初始化讀集合inset1,并在讀集合中加入相應(yīng)的描述集*/

FD_ZERO(&inset1);

FD_SET(fds[0],&inset1);

/*初始化寫(xiě)集合inset2,并在寫(xiě)集合中加入相應(yīng)的描述集*/

FD_ZERO(&inset2);

FD_SET(fds[1],&inset2);

tv.tv_sec=2;

tv.tv_usec=0;

/*循環(huán)測(cè)試該文件描述符是否準(zhǔn)備就緒,并調(diào)用select函數(shù)對(duì)相關(guān)文件描述符做對(duì)應(yīng)操作*/

while(FD_ISSET(fds[0],&inset1)||FD_ISSET(fds[1],&inset2)){

if(select(maxfd+1,&inset1,&inset2,NULL,&tv)<0)

perror("select");

else{

if(FD_ISSET(fds[0],&inset1)){

rc = read(fds[0],buf,7);

if(rc>0){

buf[rc]='\0';

printf("read: %s\n",buf);

}else

perror("read");

}

if(FD_ISSET(fds[1],&inset2)){

rc = write(fds[1],buf,7);

if(rc>0){

buf[rc]='\0';

printf("rc=%d,write: %s\n",rc,buf);

}else

perror("write");

sleep(10);

}

}

}

exit(0);

}

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多