关于事件驱动的学习三 自己手动写事件驱动

第一步:用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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值