select 的用法
[answer1] : 可以在linux 发行版本终端下敲入"man select" 查看select的基本介绍,返回值,和一些你可能看的懂得任何信息
但是想真正理解用法,还是要多看网上例子以及自己切身的调试经验。
基础信息, 下图有select的手册介绍
好了,然后就是网上铺天盖地的介绍,我是从linux必看经典编程C书册《understanding unix programming》里读到的基本的介绍
基本信息我这里先不详细赘述,主要是分享自己调试后的经验吧
主要疑惑在timeval结构体的传值。 我这里测试了两种情况 NULL 和 数值2秒
情况一:
2秒的设计, 拟设计,间隔2秒,然后看返回情况:
int len, fs_sel;
char buffer[1024];
fd_set fs_read;
FD_ZERO(&fs_read);
FD_SET(Ctrlfd, &fs_read);
struct timeval tv;
/* data */
tv.tv_sec = 2;
tv.tv_usec = 0;
for (;;)
{
/* code */
fs_sel = select(Ctrlfd+1, &fs_read,NULL, NULL, &tv);
if(fs_sel == -1){
printf("yes this error is %s, and the num is %d\n" ,strerror(errno), errno);
exit(0);
}
printf("select return\n");
if(fs_sel){
if(FD_ISSET(Ctrlfd,&fs_read)){
len += read(Ctrlfd, buffer,sizeof(buffer));
buffer[len] = '\0';
printf("rev: %s\n", buffer);
}
}
FD_ZERO(&fs_read);
FD_SET(Ctrlfd,&fs_read);
printf("fs_sel return is %d\n", fs_sel);
tv.tv_sec = 2;
tv.tv_usec = 0 ;
}
这种情况下,每次调用select后都要清零,再设置,然后才能再进一步调用正常。
但从输出情况才看到,并不是每个两秒才去检测一次返回值,select在这里并不是一个延时函数,一旦有“有效量”’还是会立即返回的, 2秒的设定只是一次检测的定时时间点,
应该理解为间隔2秒去做某事,实际上内核是一直在检测。
而且你还必须得重新设置一下检测量集,就是最后那5行的意义,如果你不这样,好像会一直不停的返回。时间结构体+FDSET都得重新设计。否则无法实现如愿的效果。
如果不如此设置,你将检测不到你想要的触发事件。
FD_ZERO(&fs_read);
FD_SET(Ctrlfd,&fs_read);
如果不如下设置,你将无法得到2秒一次的间隔效果。
不信你可以试试。
二:
NULL的情况
NULL实际上就如官方所定义的,阻塞了,实际上是基本就阻塞在调用的那个地方,等内核给你反馈就行了
代码就是去掉最后5行的调用即可。
int len, fs_sel;
char buffer[1024];
fd_set fs_read;
FD_ZERO(&fs_read);
FD_SET(Ctrlfd, &fs_read);
struct timeval tv;
/*
tv.tv_sec = 2;
tv.tv_usec = 0;
*/
for (;;)
{
/* code */
fs_sel = select(Ctrlfd+1, &fs_read,NULL, NULL, NULL);
if(fs_sel == -1){
printf("yes this error is %s, and the num is %d\n" ,strerror(errno), errno);
exit(0);
}
printf("select return\n");
if(fs_sel){
if(FD_ISSET(Ctrlfd,&fs_read)){
len += read(Ctrlfd, buffer,sizeof(buffer));
buffer[len] = '\0';
printf("rev: %s\n", buffer);
}
}
/*
FD_ZERO(&fs_read);
FD_SET(Ctrlfd,&fs_read);
printf("fs_sel return is %d\n", fs_sel);
tv.tv_sec = 2;
tv.tv_usec = 0 ;
*/
有较真的同学可能会问, 为什么NULL时,不用重新设置有效集。
这个其实很简单,因为我试过了,你加不加都他么一样。 我也不清楚上面那种情况为什么就需要加。先mark一下。