• Linux Timer定时器【转】


    转自:https://www.jianshu.com/p/66b3c75cae81

    timerfd为Linux为用户程序提供的定时器接口,该接口基于文件描述符,通过文件描述符的可读事件进行超时通知,且能够被用于epoll/select。主要有三个函数。

    头文件: include <sys/timerfd.h>

    int timerfd_create(int clockid, int flags)

    功能: 生成定时器,返回文件描述符。
    clockid: CLOCK_MONOTONIC或CLOCK_REALTIME,其中CLOCK_MONOTONIC表示获取的时间为系统重启到现在的时间,更改系统时间对其没有影响。CLOCK_REALTIME表示从1970.1.1到目前的时间,更改系统时间会更改获取的值。
    flags: TFD_NONBLOCK(非阻塞), TFD_CLOEXEC(同O_CLOEXEC)。
    return: timer的文件描述符。

    int timerfd_settime(int tfd, int flags, const struct itimerspec *newValue, struct itimerspec *oldValue)

    功能: 用于启动或关闭指定fd的定时器。
    tfd: timerfd,由timerfd_create函数返回。
    flags: 1表示设置的是绝对时间;0表示相对时间。
    newValue: 指定新的超时时间,若newValue.it_value非0则启动定时器,否则关闭定时器。若newValue.it_interval为0则定时器只定时一次,否则之后每隔设定时间超时一次。
    oldValue:不为NULL时则返回定时器这次设置之前的超时时间。
    return:失败则返回-1。

    struct timespec
    {
    time_t tv_sec; //秒
    long tv_nsec; //纳秒
    }
    struct itimerspec
    {
    struct timespec it_interval; //首次超时后,每隔it_interval超时一次
    struct timespec it_value; //首次超时时间
    }

    int timerfd_gettime(int fd, struct itimerspec *curValue)

    功能: 用于获取距离下次超时还剩下的时间。如果调用时定时器已经到期(即超过it_value时间),并且定时器处于循环模式(即it_interval不为0), 那么调用该函数后定时器重新开始计时。
    fd: timerfd,由timerfd_create函数返回。
    curValue: 返回距离下次超时剩下的时间。
    return:失败返回-1

    读取timerfd

    当定时器超时,timerfd可读,返回uint64_t类型的整数,为超时的数目(指有多少个超时未读),如果定时器没有发生超时事件,若timerfd为阻塞时,read将阻塞,若timerfd为非阻塞时,返回EAGAIN错误。如果read是的数据小于8字节以EINVAL错误返回。

    样例代码

    #include <sys/timerfd.h>  
    #include <sys/epoll.h>
    #include <unistd.h>
    #include <stdint.h>
    #include <iostream>
    using namespace std;
    
    const int EPOLL_SIZE = 10;
    
    int main(int argc, char* argv[])
    {
        int tfd, epfd, nfds;
        struct epoll_event event;
        struct epoll_event events[EPOLL_SIZE];
            
        //创建timerfd, CLOCK_REALTIME为绝对时间,TFD_NONBLOCK为非阻塞
        tfd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);  
        if (tfd < 0)
        {
            cerr << "timerfd_create error!" << endl;
            return -1;
        }   
        struct timespec startTime, intervalTime;
        startTime.tv_sec = 0;    
        startTime.tv_nsec = 1;                                //相当于立即到达超时时间
        intervalTime.tv_sec = 3;                             //首次超时后,每三秒超时一次
        intervalTime.tv_nsec = 0;
        struct itimerspec newValue;
        newValue.it_value = startTime;
        newValue.it_interval = intervalTime;
        //设置超时时间,且为相对时间
        if (timerfd_settime(tfd, 0, &newValue, NULL) < 0)
        {
            cerr << "timerfd_settime error!" << endl;
            return -1;
        }
        //用epoll来监听描述符
        epfd = epoll_create(EPOLL_SIZE);
        if (epfd < 0)
        {
            cerr << "epoll_create error!" << endl;
            return -1;
        }
    
        event.data.fd = tfd;
        event.events = EPOLLIN;
        if (epoll_ctl(epfd, EPOLL_CTL_ADD, tfd, &event) < 0)
        {
            cerr << "epoll_ctl error!" << endl;
            return -1;
        }
        
        uint64_t count = 0;
        while (1)
        {
            //非阻塞等待
            nfds = epoll_wait(epfd, events, EPOLL_SIZE, 0);
            if (nfds == 0) continue;
            for (int i = 0; i < nfds; i++)
            {
                if (events[i].events & EPOLLIN)
                {
                    uint64_t data;
                    read(events[i].data.fd, &data, sizeof(uint64_t));
                    count += data;
                    cout << "read: " << data << ", timer count: " << count << endl;
                }
            }
        }
        return 0;
    }
    

    小礼物走一走,来简书关注我



    作者:agin719
    链接:https://www.jianshu.com/p/66b3c75cae81
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 相关阅读:
    Java ES api 查询例子
    leveldb学习
    Viewstamp Replication协议
    PacificA协议
    vhost架构
    数据分片方法
    常见分布式存储系统架构分析
    数据存储(B+树 vs LSM树)
    paxos算法理解
    Raft协议理解
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/9304480.html
Copyright © 2020-2023  润新知