第一步:用select实现event侦测.
在main()函数中,发起对stdin的read flag的状态监测,如果有变化,则打印一些信息。
通过这个小程序,应该可以弄明白select是如何工作的。
#include
#include
#include
#include
#include
#include
#define CB_READ 0
#define CB_WRITE 1
#define CB_EXCEPT 2
int cb_select(int fd, int type, int timeout )
{
int result, i, j;
int maxfd;
struct timeval tv;
fd_set readset,writeset, exset;
FD_ZERO( &readset );
FD_ZERO( &writeset);
FD_ZERO( &exset );
switch(type)
{
case CB_READ:
FD_SET(fd, &readset );
break;
case CB_WRITE:
FD_SET(fd, &writeset );
break;
case CB_EXCEPT:
FD_SET(fd, &exset);
break;
default:
break;
}
tv.tv_sec = timeout;
tv.tv_usec = 0;
maxfd = fd;
result = select(maxfd+1, &readset, &writeset,&exset, &tv );
if( result == -1 )
{
perror( "ERROR: select() suffers errors, and return -1/n" );
}
else if( result )
{
// everything is going well till now
if( FD_ISSET( fd, &readset )
|| FD_ISSET(fd, &writeset )
|| FD_ISSET(fd, &exset) )
{
//now we can call back
printf("here, we can call back now/n");
}
}
else
{
printf("Time is out!/n");
}
}
void main()
{
printf("select is started!/n");
cb_select( 1,CB_READ, 10,stdin_cb, timeout_cb );
printf("select() returned/n");
}
这个方式可以简单的探测一个fd的状态变化,下面可以模拟如何探测多个fd的状态变化。
实现探测多个fd的状态变化有多种方式,我第一直觉像到的是,多次调用select(),即有几个fd就调用几次select,
但是考虑到select()是阻塞型接口,那么或者对多个fd的select操作顺序执行,或者就只能一个fd对应一个探测线程(多线程),每个线程里调用select。
这两种方式都不是很好的方案。还有一种方案是:充分利用select能够同时对多个fd进行状态监测这个特点,用一个select监控多个fd.
考虑到select()探测到任何一个状态变化都会立即返回,我们可以select()接口被循环调用,这样自始至终保持对多个fd的状态监测。
附加:
在进行这项工作之前,我们必须得了解select()的一些输入输出变化情况:
result = select( max_fd+1, &readset, &writeset, &exset, &tv )
注意,后四位同时是输入也是输出。
例子一:
FD_SET(1, readset);
FD_SET(12,readset);
FD_SET(123, writeset);
tv.tv_sec = 10
select ()... 这个时候用户随便键入一个字符,即让1号fd获得读的信号,
则readset被重置为2( 二进制的fd=1,我也没搞清如何换算的),writeset为0,tv.tv_sec = 8 说明从select被开始调用到获得信号中间隔了2秒
例子二,
与例子一同有的输入设置,调用select(),但是自始至终没有输入,则输出情况是:readset, writeset,exset都为0,而tv.tv_sec也为0
这两个例子给我们的提示是:可以借助select() 的输出原理,判断到底哪个fd收到信号,判断这个信号花费了多少时间
第二步, 同时检测多个event
.... to be continued!
这个模型能够很好的执行对多个fd进行状态扫描和timeout监测,但这里有个很大的问题。 各个callback程序一定耗时很短,这样时间的计算就是正确的。如果callback耗时很长,各个fd的timeout计时会出错外,连整个loop过程都被阻塞。
现在考虑用signal让callback的过程由signal发起。
第三步,使用signal启动异步callback
在main()函数中,发起对stdin的read flag的状态监测,如果有变化,则打印一些信息。
通过这个小程序,应该可以弄明白select是如何工作的。
#include
#include
#include
#include
#include
#include
#define CB_READ 0
#define CB_WRITE 1
#define CB_EXCEPT 2
int cb_select(int fd, int type, int timeout )
{
int result, i, j;
int maxfd;
struct timeval tv;
fd_set readset,writeset, exset;
FD_ZERO( &readset );
FD_ZERO( &writeset);
FD_ZERO( &exset );
switch(type)
{
case CB_READ:
FD_SET(fd, &readset );
break;
case CB_WRITE:
FD_SET(fd, &writeset );
break;
case CB_EXCEPT:
FD_SET(fd, &exset);
break;
default:
break;
}
tv.tv_sec = timeout;
tv.tv_usec = 0;
maxfd = fd;
result = select(maxfd+1, &readset, &writeset,&exset, &tv );
if( result == -1 )
{
perror( "ERROR: select() suffers errors, and return -1/n" );
}
else if( result )
{
// everything is going well till now
if( FD_ISSET( fd, &readset )
|| FD_ISSET(fd, &writeset )
|| FD_ISSET(fd, &exset) )
{
//now we can call back
printf("here, we can call back now/n");
}
}
else
{
printf("Time is out!/n");
}
}
void main()
{
printf("select is started!/n");
cb_select( 1,CB_READ, 10,stdin_cb, timeout_cb );
printf("select() returned/n");
}
这个方式可以简单的探测一个fd的状态变化,下面可以模拟如何探测多个fd的状态变化。
实现探测多个fd的状态变化有多种方式,我第一直觉像到的是,多次调用select(),即有几个fd就调用几次select,
但是考虑到select()是阻塞型接口,那么或者对多个fd的select操作顺序执行,或者就只能一个fd对应一个探测线程(多线程),每个线程里调用select。
这两种方式都不是很好的方案。还有一种方案是:充分利用select能够同时对多个fd进行状态监测这个特点,用一个select监控多个fd.
考虑到select()探测到任何一个状态变化都会立即返回,我们可以select()接口被循环调用,这样自始至终保持对多个fd的状态监测。
附加:
在进行这项工作之前,我们必须得了解select()的一些输入输出变化情况:
result = select( max_fd+1, &readset, &writeset, &exset, &tv )
注意,后四位同时是输入也是输出。
例子一:
FD_SET(1, readset);
FD_SET(12,readset);
FD_SET(123, writeset);
tv.tv_sec = 10
select ()... 这个时候用户随便键入一个字符,即让1号fd获得读的信号,
则readset被重置为2( 二进制的fd=1,我也没搞清如何换算的),writeset为0,tv.tv_sec = 8 说明从select被开始调用到获得信号中间隔了2秒
例子二,
与例子一同有的输入设置,调用select(),但是自始至终没有输入,则输出情况是:readset, writeset,exset都为0,而tv.tv_sec也为0
这两个例子给我们的提示是:可以借助select() 的输出原理,判断到底哪个fd收到信号,判断这个信号花费了多少时间
第二步, 同时检测多个event
.... to be continued!
这个模型能够很好的执行对多个fd进行状态扫描和timeout监测,但这里有个很大的问题。 各个callback程序一定耗时很短,这样时间的计算就是正确的。如果callback耗时很长,各个fd的timeout计时会出错外,连整个loop过程都被阻塞。
现在考虑用signal让callback的过程由signal发起。
第三步,使用signal启动异步callback