timerfd

作者: wayyyy | 来源:发表于2020-12-30 11:35 被阅读0次

Linux内核于内核2.6之后提供了一种创建定时器的方法,那就是Linux特有的timerfd文件描述符(一切皆文件),这也意味着可以用多路复用来监听并读取。该接口共有3个API。

  • timerfd_create

    #include <sys/timerfd.h>
    int timerfd_create(int clockid, int flags);
    
    成功返回一个指代该对象的文件描述符, 失败返  回-1及errno
    
    • 第一个cokckid 可以设置为:CLOCK_REALTIMECLOCK_MONOTONIC
      • CLOCK_REALTIME 表示可设定的系统级别时钟,更改系统时间会更改获取的值。也就是说,它以系统时间为坐标。
      • CLOCK_MONOTONIC
        不可设定的恒定态时钟,更改系统时间对齐没有影响。
    • 第二个参数flags, 支持TFD_CLOEXECTFD_NONBLOCK0
      • TFD_CLOEXEC 为新的文件描述符设置运行时关闭标志。(待补充)
      • TFD_NONBLOCK 为底层的打开文件描述符设置 O_NONBLOCK 标志, 随后的读操作将是非阻塞的,
  • timerfd_settime

    #include <sys/timerfd.h>
    
    int timerfd_settime(int fd, 
                        int flags, 
                        const struct itimerspec* new_value, 
                        struct itimerspec* old_value);
    
    成功返回0, 失败返回-1和 errno
    

    它的作用是启动或者停止由文件描述符fd指定的定时器。第二个参数和第三个参数都是struct timespec类型。

    struct itimerspec 
    {
        struct timespec it_interval;   //间隔时间
        struct timespec it_value;      //第一次到期时间
    };
    
    struct timespec 
    {
        time_t tv_sec;    //秒
        long tv_nsec;    //纳秒
    };
    
    • new_value 为定时器指定新设置新的超时时间,若 newValue.it_value非 0 则启动定时器,否则关闭定时器。若 newValue.it_interval 为 0 则定时器只定时一次,否则之后每隔设定时间超时一次。
    • old_value 用来返回定时器的前一设置, 如果不关心, 可将其设置为 NULL,不为 NULL 时则返回定时器这次设置之前的超时时间。
  • timerfd_gettime

    #include <sys/timerfd.h>
    int timerfd_gettime(int fd, struct itimerspec *curr_value);
    
    成功返回0, 失败返回-1和errno
    

    返回文件描述符 fd 所标识定时器的间隔及剩余时间。
    间隔和距离下次到期的时间均返回到 curr_value 指向的结构体。
    如果返回的结构中 curr_value.it_value 中所有字段值均为0, 那么该定时器已经解除, 如果返回的结构 curr_value.it_interval 中两字段值均为0, 那么该定时器只会到期一次, 到期时间在 curr_value.it_value 中给出

配合使用epoll监听定时器
#include <time.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <assert.h>
using namespace std;

const int MAXNUM = 20;

int main(int argc, char *argv[])
{
    struct itimerspec new_value;
    struct timespec now;
    uint64_t exp;
    ssize_t s;

    int ret = clock_gettime(CLOCK_REALTIME, &now);//获取时钟时间
    assert(ret != -1);

    new_value.it_value.tv_sec = 5; //第一次到期的时间
    new_value.it_value.tv_nsec = now.tv_nsec; 

    new_value.it_interval.tv_sec = 1;      //之后每次到期的时间间隔
    new_value.it_interval.tv_nsec = 0;

    int timefd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK); // 构建了一个定时器
    assert(timefd != -1);

    ret = timerfd_settime(timefd, 0, &new_value, NULL);//启动定时器
    assert(ret != -1);

    cout << "timer started" << endl; // 定时器开启啦!


    int epollfd = epoll_create(1);  //创建epoll实例对象

    struct epoll_event ev;
    struct epoll_event events[MAXNUM];
    ev.data.fd = timefd;
    ev.events = EPOLLIN | EPOLLET;
    epoll_ctl(epollfd, EPOLL_CTL_ADD, timefd, &ev); //添加到epoll事件集合

    for (; ;) 
    {
        int num = epoll_wait(epollfd, events, MAXNUM, 0);
        assert(num >= 0);

        for (int i = 0; i < num; i++) 
        {
            if (events[i].events & EPOLLIN) 
            {
                //....处理其他事件
                if (events[i].data.fd == timefd) 
                {
                    s = read(events[i].data.fd, &exp, sizeof(uint64_t)); //需要读出uint64_t大小, 不然会发生错误
                    assert(s == sizeof(uint64_t));
                    cout << "here is timer" << endl;
                }
            }
        }
    }

    close(timefd);
    close(epollfd);

    return 0;
}

参考资料
1.https://blog.csdn.net/weixin_36888577/article/details/81570793

相关文章

  • linux手册翻译——timerfd_create(2)

    timerfd_create, timerfd_settime, timerfd_gettime - timers...

  • timerfd

    Linux内核于内核2.6之后提供了一种创建定时器的方法,那就是Linux特有的timerfd文件描述符(一切皆文...

  • timerfd总结

    前言 又是隔了不短时间,不过每天也没怎么放松,一部分是自己在看libevent和udp通信的东西,暂时处于学习阶段...

  • timerfd的使用方法

    timerfd的使用方法 文章来自:http://blog.csdn.net/yusiguyuan/article...

  • Linux timerfd系列函数

    使用Linux 提供的timerfd和epoll可以实现Timer的定时唤醒功能. 需要引入头文件#include...

  • Linux Timer定时器

    timerfd为Linux为用户程序提供的定时器接口,该接口基于文件描述符,通过文件描述符的可读事件进行超时通知,...

网友评论

      本文标题:timerfd

      本文链接:https://www.haomeiwen.com/subject/dfaadhtx.html