首先搞清楚select的参数、返回值,代表些什么。
1、头文件 #include <sys/select.h>
2、参数 函数原型:int select (int maxfd + 1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval * timeout);
参数一:最大的文件描述符加1。
参数二:用于检查可读性,
参数三:用于检查可写性,
参数四:用于检查带外数据,
参数五:一个指向timeval结构的指针,用于决定select等待I/o的最长时间。如果为空将一直等待。timeval结构的定义:struct timeval{
long tv_sec; // seconds
long tv_usec; // microseconds
}
3、返回值
>0:就绪描述字的正数目
-1:出错
0 :超时
readset writeset exceptset指定我们要让内核测试读、写和异常条件的描述字。如果对某一个的条件不感兴趣,就可以把它设为NULL。如果三个指针都为NULL,我们就有了一个比sleep()函数更为精确的定时器(sleep()以毫秒为最小单位,这个以微秒为单位)。
以下是转载的一篇文章
我们来看看程序:
-
-
-
-
-
-
- int serial_read(int fd, char *str, unsigned int len, unsigned int timeout)
- {
- fd_set rfds;
- struct timeval tv;
- int ret;
- int sret;
- int readlen = 0;
- char * ptr;
-
- ptr = str;
-
- FD_ZERO(&rfds);
- FD_SET(fd,&rfds);
-
-
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout%1000)*1000;
-
-
-
-
-
-
-
- while(readlen < len)
- {
- sret = select(fd+1,&rfds,NULL,NULL,&tv);
-
- if(sret == -1)
- {
- perror("select:");
- break;
- }
- else if(sret > 0)
- {
- ret = read(fd,ptr,1);
- printf("sec: %d,usec: %d\n",tv.tv_sec,tv.tv_usec);
- if(ret < 0)
- {
- perror("read err:");
- break;
- }
- else if(ret == 0)
- break;
-
- readlen += ret;
- ptr += ret;
- }
- else
- {
- printf("timeout!\n");
- break;
- }
- }
-
- return readlen;
- }
一目了然,计时从fd这个设备描述符读取数据,读入的数据存入str中,长度为len,超时时间为timeout。
这里大家一定会很奇怪,为什么我要一个个字节的读出数据?这个函数原来也不是笔者写的,是参照一个大牛的写法,我一开始也没明白,后来终于明白:因为要超时!
tv这个参数,会在记录调用了select后消耗的时间,这样当我每次while循环的时候,就可以检测并且记录tv还剩多少时间能让我消耗,若tv的值为0了,那么就是超时了。
打开串口,我们来看看运行结果:
可以看到我从串口输入了11个数据,每传入一个字节的数据大概耗时70us
(笔者输入的是i love you ,但是原先输入了多次i love you linux and unix and meego缓冲区没有清除,35个字节太长没有办法截图,谅解~~~)
如此就可以实现超时读数据,select方法原来还有这样用,我也是刚刚发现,和大家分享!