系统相关
首页 > 系统相关> > Linux C/C++定时器

Linux C/C++定时器

作者:互联网

1. 定时接口

     特点:有一定的精度,但是会使线程挂起。

     特点:采用了信号SIGALRM,由于SIGALRM信号不可靠,会造成超时通知不可靠,而且多线程中处理信号比较复杂。

     特点:先创建,再设置。创建时可以配置回调;精度在纳秒级别;需要librt库;想要与业务程序配合,需要进行一定的封装,封装成本比较高。

     特点:poll/epoll是毫秒级的(millisecond),select超时参数是struct timeval,是微秒级的(microsecond)。

        epoll的优势很明显,能将定时功能完美的融入已有的event loop里,有着天然的高并发的能力,millisecond级的精度也足够用。

 

2. 系统时间

    特点: 一条汇编指令rdtscp即可,libco就是优先使用这个方法获取时间的。

    特点:调用频繁的话,可能造成损失性能。但是Linux 2.6.32后可以指定参数 CLOCK_REALTIME_COARSE 和 CLOCK_MONOTONIC_COARSE,粗粒度地获取时间,而不需要发生上下文切换。

       和gettimeofday()一样也是vdso技术,使用_COARSE后缀获取的时间,精度是millisecond级。

 

3. 定时器的设计

  从上述的总结,开源实现和别人的总结中多路复用模式可以达到更好的精度和并发。

  epoll 每次只能设置一个超时时间,不能满足需求。

  ① 结合clock_gettime获取系统时间,然后再设置epoll_wait的定时时间。

    这种设计下需要使用容器保存所有的定时时间,epoll每次配置最快超时的时间为epoll_wait的定时时间。

    需要选择合适的超时时间保存的容器,保证可以用O(1)获取到最小的那个超时时间。

  ② 结合Timerfd API

    Linux内核2.6.25版本中添加的接口,把超时事件触发为文件描述符,超时发生后,文件描述符可读。

    这种机制下超时事件成为了普通的IO事件,也可以设置阻塞/非阻塞,timerfd的精度达到了纳秒级。

    Note:libevent2.1中也支持了timerfd,特点是:高效,精确。

      每一个超时事件都用timerfd_create()创建对应的fd,放到epoll中统一管理。

      每增加一个定时事件,需要增加3个系统调用。文件描述符是稀缺资源。定时器过多会浪费。

      libevent使用的方法:每个event loop共享一个timerfd,每次循环事件之前,取出最近一个超时事件的时间,将timerfd设置为这个超时时间。

 

4. 超时时间的容器

    libevent 使用的这种模式。

    libco 使用的这种模式。

    Type          add       exec
    list          O(1)      O(n)
    min-heap        O(lgn)     O(1)
     time wheel       O(1)      O(n)

 

标签:定时器,epoll,C++,时间,timerfd,Linux,定时,超时,精度
来源: https://www.cnblogs.com/yangdadahome/p/14968115.html