预览加载中,请您耐心等待几秒...
1/4
2/4
3/4
4/4

在线预览结束,喜欢就下载吧,查找使用更方便

如果您无法下载资料,请参考说明:

1、部分资料下载需要金币,请确保您的账户上有足够的金币

2、已购买过的文档,再次下载不重复扣费

3、资料包下载后请先用软件解压,在使用对应软件打开

select系统调用是用来让我们的程序监视多个文件描述符(filedescrīptor)的状态变化的。程序会停在select这里等待,直到被监视的文件描述符有某一个或多个发生了状态改变。select()的机制中提供一fd_set的数据结构,实际上是一long类型的数组,每一个数组元素都能与一打开的文件描述符(不管是Socket描述符,还是其他文件或命名管道或设备描述符)建立联系,建立联系的工作由程序员完成,当调用select()时,由内核根据IO状态修改fd_set的内容,由此来通知执行了select()的进程哪一Socket或文件可读,select函数原型如下: intselect(intnfds,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,structtimeval*timeout); 函数的最后一个参数timeout显然是一个超时时间值,其类型是structtimeval*,即一个structtimeval结构的变量的指针,所以我们在程序里要申明一个structtimevaltv;然后把变量tv的地址&tv传递给select函数。structtimeval结构如下: structtimeval{ longtv_sec;/*seconds*/ longtv_usec;/*microseconds } 第2、3、4三个参数的类型是一样的:fd_set*,即我们在程序里要申明几个fd_set类型的变量,比如定义了rfds,wfds,efds。 另外关于fd_set类型的变量,还有一组标准的宏定义来处理此类变量: FD_ZERO(fd_set*fdset):清空fdset与所有文件描述符的联系。 FD_SET(intfd,fd_set*fdset):建立文件描述符fd与fdset的联系。 FD_CLR(intfd,fd_set*fdset):清除文件描述符fd与fdset的联系。 FD_ISSET(intfd,fd_set*fdset):检查fd_set联系的文件描述符fd是否可读写,>0表示可读写。 (关于fd_set及相关宏的定义见/usr/include/sys/types.h)定义的这三个参数都是描述符的集合,第一个rfds是用来保存这样的描述符的:当描述符的状态变成可读的时系统就会告诉select函数返回,第二个wfds是指有描述符状态变成可写的时系统就会告诉select函数返回,第三个参数efds是特殊情况,即描述符上有特殊情况发生时系统会告诉select函数返回。下面以一个输入为例来说明: intfd1,fd2;/*在定义两个描述符*/ fd1=socket(...);/*创建socket连接*/ fd2=open(“/dev/tyS0”,O_RDWR);/*打开一个串口*/ FD_ZERO(&rfds);/*用select函数之前先把集合清零*/ FD_SET(fd1,&rfds);/*分别把2个描述符加入读监视集合里去*/ FD_SET(fd2,&rfds); intmaxfd=0; maxfd=(fd1>fd2)?(fd1+1):(fd2+1);/*注意是最大值还要加1*/ ret=select(maxfd,&rfds,NULL,NULL,&tv);/*然后调用select函数*/ 这样就可以使用一个开关语句(switch语句)来判断到底是哪一个输入源在输入数据。具体判断如下: switch(ret){ case-1:perror("select");/*这说明select函数出错*/ case0:printf("超时/n");/*说明在设定的时间内,socket的状态没有发生变化*/ default: if(FD_ISSET(fd1,&rfds))处理函数1();/*socket有数据来*/ if(FD_ISSET(fd2,&rfds))处理函数2();/*ttyS0有数据来*/ } 注:fgets()函数只有遇到'\n'时fd==0才会“readyforread”