注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

muduo库的一些心得之二定时器的深入理解Poll与timerfd的用法  

2014-12-24 14:57:52|  分类: LINUX编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

muduo库的一些心得之二定时器的深入理解Polltimerfd的用法

 

 

想把原来梳理过得timerfd的用法写一个定时器类来用,结果发现原来的理解并不深入,有很多的东西都是模棱两可的。所以还是需要再认真的总结一下:

1、  首先,对设置文件句柄timerfd为阻塞或者非阻塞,是有所不同的。在设置成阻塞的情况下,read poll都会阻塞当前进程或者线程。而非阻塞则不会。

真正 有用的其实就在这里,从前面知道,要想完成一个好的定时器如果使用线程阻塞的方法是不好的,最好的方法还是使用异步的回调。所以这里使用非阻塞的定时器文件描述符,再加上回调函数,就可以实现一个异步的回调定时器。这个方法是非常棒的。

2、  对时间的设置有相对时间和绝对时间之分,这个在前面的博文中说过,网上也有非常详细的资料,这里就不再细说。

3、  Read的控制。这个也得说明一下,其实正如前面所说的,Read真正的作用在于清除LT触发的连续操作。防止同一个触发引起不断的动作。这才是真正重要的,前面对这个了解和认识的不够深刻,下面的代码会进行说明。

4、  再有一个就是一个非常恶心的陷阱。那就是为不同的类型的对齐和干扰问题。这个原来在Keil中遇到过一次,一个有符号和一个符号的自动转换引起的BUG问题。这里涉及的uint64_tint的问题。

5、  一定要把大脑的思绪理清楚了,不能盲目的瞎干,结果就是越弄越乱。

6、  重视细节,对一些返回和循环的控制不能掉以轻心。

下来看代码:

void printTime()

         struct timeval tv; 

         gettimeofday(&tv, NULL); 

         printf("printTime:  current time:%ld.%ld ", tv.tv_sec, tv.tv_usec);

}

 

int main(int argc, char *argv[])

{

   /*struct timespec now;

   if (clock_gettime(CLOCK_REALTIME, &now) == -1)

            handle_error("clock_gettime");

 

   struct itimerspec new_value;

   new_value.it_value.tv_sec = now.tv_sec + 1; //atoi(argv[1]);

   new_value.it_value.tv_nsec = now.tv_nsec;

   new_value.it_interval.tv_sec = 1;//atoi(argv[2]);

   new_value.it_interval.tv_nsec = 0;

*/

   struct itimerspec howlog;

   bzero(&howlog,sizeof howlog);

   howlog.it_value.tv_sec = 3;

   howlog.it_value.tv_nsec = 0;

   howlog.it_interval.tv_sec = 5;

   howlog.it_interval.tv_nsec = 0;

 

   int fd = timerfd_create(/*CLOCK_REALTIME*/CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);

   if (fd == -1)

            handle_error("timerfd_create");

 

   if (timerfd_settime(fd, /*TFD_TIMER_ABSTIME*/0, &howlog, NULL) == -1)

            handle_error("timerfd_settime");

 

   printTime();

   printf("timer started----------------\n");

 

   struct pollfd myp;

   myp.fd = fd;

   myp.events = POLLIN | POLLPRI;

   myp.revents = 0;

 

  uint64_t /*int*/  cur = 0;

  //int tnum = ::poll(&myp,sizeof myp,20000);

uint64_t tot_exp =0;

   /*while(1)for (;;) *//*uint64_t tot_exp =0; tot_exp <4;*/

   //for (int len = 0;len< 300;len++)   

for (uint64_t len = 0;len< 100;len++)

   {

       uint64_t exp;

printf("front is value---:%d\n",cur++);

int numevent =   ::poll(&myp,sizeof(myp),10000);

           //printf("front is value:%d\n",fd);

            ssize_t s = read(fd, &exp, sizeof(uint64_t));

           //printf("end is value:%d\n",fd);

            //if (s != sizeof(uint64_t))

                      //handle_error("read");

           if (s < 0)

            {

//printf("-1 is value!\n");

              continue;

             }

            tot_exp += exp;

            printTime();

            printf("read: %llu; total=%llu\n",exp, tot_exp);

   }

 

   exit(EXIT_SUCCESS);

}

仍然是老代码,但装了新酒。

上面的红色部分,是足足折腾了一天,一直都发现,只要是用uint64_t的循环或者无限循环,都没有问题,(使用int len = 0;len< 300;len++类似的代码就不行)但没有引起重视。另外还有一种情况,即使正确的使用前面的循环,只要是在循环前定义了int型的变量,除非放到函数外做全局的,否则同样产生异常。

这个异常非常奇怪,跟踪时发现pollfd文件描述符的数字是正常的,但经过三几次以后,这个fd就变化了,可能原因就是前面说的那个intuint64_t对齐的原因。它引起的结果就是在Read时,用perror时会发现,他报一个“不可用的(坏的)文件描述符”。

不过前面的加红的poll那个返回值 改成uint64_t却不起作用,看来还是声明有些问题。

后来看陈硕的代码,发现人家单独把这个Read控制了起来,就防止出现类似的错误,学习别人的代码还是大有裨益啊。

注意:g++  -o  timeold  timefd-old.cpp –lrt  记得加这个,否则找不到clock_gettime

  评论这张
 
阅读(477)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017