fd定时器--timerfd学习

定时器

可以用系统定时器信号SIGALARM

最近工作需要于是又发现了一个新玩意timerfd配合epoll使用。

man 手册看一下

TIMERFD_CREATE(2)                         Linux Programmer's Manual                         TIMERFD_CREATE(2)

NAME
       timerfd_create, timerfd_settime, timerfd_gettime - timers that notify via file descriptors

SYNOPSIS
       #include <sys/timerfd.h>

       int timerfd_create(int clockid, int flags);

       int timerfd_settime(int fd, int flags,
                           const struct itimerspec *new_value,
                           struct itimerspec *old_value);

       int timerfd_gettime(int fd, struct itimerspec *curr_value);

DESCRIPTION
       These  system  calls  create and operate on a timer that delivers timer expiration notifications via a
       file descriptor.  They provide an alternative to the use of setitimer(2) or timer_create(2), with  the
       advantage that the file descriptor may be monitored by select(2), poll(2), and epoll(7).

       The  use of these three system calls is analogous to the use of timer_create(2), timer_settime(2), and
       timer_gettime(2).  (There is no analog of timer_getoverrun(2), since that functionality is provided by
       read(2), as described below.)

这是一个专门针对fd的定时器,通过fd可以读取定时数据(定时时间到了就会有数据回来,否则阻塞(阻塞模式))。

结合epoll使用先弄个epoll出来

/* init epoll */
int epollInit(){
    int epFd = epoll_create(EPOLL_SIZE);
    if (epFd < 0){
        perror("epoll create");
        return -1;
    }
    return epFd;
}

然后在弄个timerfd,并把它加入到epoll 事件中

int TimerFdInit(int epFd)
{
    struct itimerspec new_value;
    /*init time*/
    new_value.it_value.tv_sec = 1;
    new_value.it_value.tv_nsec = 0;
    /*time interval*/
    new_value.it_interval.tv_sec = 1;
    new_value.it_interval.tv_nsec = 0;

    int timerFd = timerfd_create(CLOCK_MONOTONIC, 0);
    if (timerFd < 0) {
        cerr<<strerror(errno)<<endl;
        return -1;
    }

    int ret = timerfd_settime(timerFd, 0, &new_value, NULL);
    if (ret < 0) {
        cerr<<strerror(errno)<<endl;
        close(timerFd);
        return -1;
    }
    /* add to epoll */
    struct epoll_event ev;
    ev.events = EPOLLIN | EPOLLHUP | EPOLLRDHUP;
    ev.data.fd = timerFd;
    epoll_ctl(epFd, EPOLL_CTL_ADD, timerFd, &ev);
    return timerFd;
}

接下来就去epoll_wait循环等待这个定时器的数据

int epollHandle(int epFd, int timerFd)
{
    struct epoll_event epEvents[EPOLL_SIZE] = {};
    int timeOut = -1;
    uint64_t totalExp = 0;
    while (1)
    {
        //blocked
        int eventNum = epoll_wait(epFd, epEvents, EPOLL_SIZE, timeOut);
        if(eventNum < 0) {
            perror("epoll failure");
            return -1;
        }

        //handle epEvents
        for(int i = 0; i < eventNum; ++i) {
            int tmpFd = epEvents[i].data.fd;
            if(epEvents[i].events & EPOLLIN) {
                if (timerFd == tmpFd) {
                    /*handle timerFd*/
                    uint64_t tmpExp = 0;
                    /*must read*/
                    read(timerFd, &tmpExp, sizeof(uint64_t));
                    totalExp += tmpExp;
                    cout<<"timer count "<<totalExp<<endl;
                }
              }
           }
        }
    return 0;
}
原文地址:https://www.cnblogs.com/tid-think/p/10779026.html