zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Linux内核网络协议栈优化总纲
    Java实现 蓝桥杯VIP 算法训练 连续正整数的和
    Java实现 蓝桥杯VIP 算法训练 连续正整数的和
    Java实现 蓝桥杯VIP 算法训练 寂寞的数
    Java实现 蓝桥杯VIP 算法训练 寂寞的数
    Java实现 蓝桥杯VIP 算法训练 学做菜
    Java实现 蓝桥杯VIP 算法训练 学做菜
    Java实现 蓝桥杯VIP 算法训练 判断字符位置
    Java实现 蓝桥杯VIP 算法训练 判断字符位置
    Java实现 蓝桥杯VIP 算法训练 链表数据求和操作
  • 原文地址:https://www.cnblogs.com/tid-think/p/10779026.html
Copyright © 2011-2022 走看看