• linux timerfd系列函数总结


    网上关于timerfd的文章很多,在这儿归纳总结一下方便以后使用,顺便贴出一个timerfd配合epoll使用的简单例子

    一、timerfd系列函数

      timerfd是Linux为用户程序提供的一个定时器接口。这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,因此可以配合select/poll/epoll等使用。
    下面对timerfd系列函数先做一个简单的介绍:

    (1)timerfd_create()函数

    #include <sys/timerfd.h>
    
    int timerfd_create(int clockid, int flags);
    /* 
    timerfd_create()函数创建一个定时器对象,同时返回一个与之关联的文件描述符。
    clockid:clockid标识指定的时钟计数器,可选值(CLOCK_REALTIME、CLOCK_MONOTONIC。。。)
    CLOCK_REALTIME:系统实时时间,随系统实时时间改变而改变,即从UTC1970-1-1 0:0:0开始计时,中间时刻如果系统时间被用户改成其他,则对应的时间相应改变
    CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
    flags:参数flags(TFD_NONBLOCK(非阻塞模式)/TFD_CLOEXEC(表示当程序执行exec函数时本fd将被系统自动关闭,表示不传递)
    */

    (2)timerfd_settime()函数

     1 #include <sys/timerfd.h>
     2 
     3 struct timespec {
     4     time_t tv_sec;                /* Seconds */
     5     long   tv_nsec;               /* Nanoseconds */
     6 };
     7 
     8 struct itimerspec {
     9     struct timespec it_interval;  /* Interval for periodic timer (定时间隔周期)*/
    10     struct timespec it_value;     /* Initial expiration (第一次超时时间)*/
    11 };
    12 int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
    13 /*
    14     timerfd_settime()此函数用于设置新的超时时间,并开始计时,能够启动和停止定时器;
    15     fd: 参数fd是timerfd_create函数返回的文件句柄
    16     flags:参数flags为1代表设置的是绝对时间(TFD_TIMER_ABSTIME 表示绝对定时器);为0代表相对时间。
    17     new_value: 参数new_value指定定时器的超时时间以及超时间隔时间
    18     old_value: 如果old_value不为NULL, old_vlaue返回之前定时器设置的超时时间,具体参考timerfd_gettime()函数
    19     
    20     ** it_interval不为0则表示是周期性定时器。
    21        it_value和it_interval都为0表示停止定时器
    22 */

    (3)timerfd_gettime()函数

    1 int timerfd_gettime(int fd, struct itimerspec *curr_value);
    2 /*
    3     timerfd_gettime()函数获取距离下次超时剩余的时间
    4     curr_value.it_value 字段表示距离下次超时的时间,如果改值为0,表示计时器已经解除
    5     改字段表示的值永远是一个相对值,无论TFD_TIMER_ABSTIME是否被设置
    6     curr_value.it_interval 定时器间隔时间
    7 */
    1 uint64_t exp = 0;
    2 read(fd, &exp, sizeof(uint64_t)); 
    3 //可以用read函数读取计时器的超时次数,改值是一个8字节无符号的长整型

    (4)下面贴出一个timerfd配合epoll函数的简单例子

      1 /********************************************************
      2 * Filename: timerfd.c
      3 * Author: zhangwj
      4 * Desprition: a sample program of timerfd
      5 * Date: 2017-04-17
      6 * Warnning:
      7 ********************************************************/
      8 #include <stdio.h>
      9 #include <stdint.h>
     10 #include <string.h>
     11 #include <stdlib.h>
     12 #include <pthread.h>
     13 #include <errno.h>
     14 #include <sys/epoll.h>
     15 #include <sys/timerfd.h>
     16 
     17 #if 0
     18 struct timespec {
     19     time_t tv_sec;                /* Seconds */
     20     long   tv_nsec;               /* Nanoseconds */
     21 };
     22 
     23 struct itimerspec {
     24     struct timespec it_interval;  /* Interval for periodic timer */
     25     struct timespec it_value;     /* Initial expiration */
     26 };
     27 #endif
     28 
     29 #define EPOLL_LISTEN_CNT        256
     30 #define EPOLL_LISTEN_TIMEOUT    500
     31 
     32 #define LOG_DEBUG_ON 1
     33 
     34 #ifdef LOG_DEBUG_ON 
     35 #define LOG_DEBUG(fmt, args...) 
     36     do {  
     37         printf("[DEBUG]:");
     38         printf(fmt "
    ", ##args); 
     39     } while(0);
     40 #define LOG_INFO(fmt, args...) 
     41     do { 
     42         printf("[INFO]:");
     43         printf(fmt "
    ", ##args); 
     44     } while(0);
     45 #define LOG_WARNING(fmt, args...) 
     46     do { 
     47         printf("[WARNING]:");
     48         printf(fmt "
    ", ##args); 
     49     } while(0);
     50 #else
     51 #define LOG_DEBUG(fmt, args...) 
     52 #define LOG_INFO(fmt, args...) 
     53 #define LOG_WARNING(fmt, args...) 
     54 #endif
     55 #define LOG_ERROR(fmt, args...) 
     56     do{ 
     57         printf("[ERROR]:");
     58         printf(fmt "
    ", ##args);
     59     }while(0);
     60 
     61 #define handle_error(msg) 
     62         do { perror(msg); exit(EXIT_FAILURE); } while (0)
     63 
     64 static int g_epollfd = -1;
     65 static int g_timerfd = -1;
     66 uint64_t tot_exp = 0;
     67 
     68 static void help(void)
     69 {
     70     exit(0);
     71 }
     72 
     73 static void print_elapsed_time(void)
     74 {
     75     static struct timespec start;
     76     struct timespec curr;
     77     static int first_call = 1;
     78     int secs, nsecs;
     79     
     80     if (first_call) {
     81         first_call = 0;
     82         if (clock_gettime(CLOCK_MONOTONIC, &start) == -1) 
     83             handle_error("clock_gettime");
     84     }   
     85     
     86     if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1) 
     87         handle_error("clock_gettime");
     88     
     89     secs = curr.tv_sec - start.tv_sec;
     90     nsecs = curr.tv_nsec - start.tv_nsec;
     91     if (nsecs < 0) {
     92         secs--;
     93         nsecs += 1000000000;
     94     }   
     95     printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000);
     96 }
     97 
     98 void timerfd_handler(int fd)
     99 {
    100     uint64_t exp = 0;
    101     
    102     read(fd, &exp, sizeof(uint64_t)); 
    103     tot_exp += exp;
    104     print_elapsed_time();
    105     printf("read: %llu, total: %llu
    ", (unsigned long long)exp, (unsigned long long)tot_exp);
    106 
    107     return;
    108 }
    109 
    110 void epoll_event_handle(void)
    111 {
    112     int i = 0;
    113     int fd_cnt = 0;
    114     int sfd;
    115     struct epoll_event events[EPOLL_LISTEN_CNT];    
    116 
    117     memset(events, 0, sizeof(events));
    118     while(1) 
    119     {   
    120         /* wait epoll event */
    121         fd_cnt = epoll_wait(g_epollfd, events, EPOLL_LISTEN_CNT, EPOLL_LISTEN_TIMEOUT); 
    122         for(i = 0; i < fd_cnt; i++) 
    123         {   
    124             sfd = events[i].data.fd;
    125             if(events[i].events & EPOLLIN) 
    126             {   
    127                 if (sfd == g_timerfd) 
    128                 {
    129                     timerfd_handler(sfd); 
    130                 }   
    131             }   
    132         } 
    133     }   
    134 }
    135 
    136 int epoll_add_fd(int fd)
    137 {
    138     int ret;
    139     struct epoll_event event;
    140 
    141     memset(&event, 0, sizeof(event));
    142     event.data.fd = fd;
    143     event.events = EPOLLIN | EPOLLET;
    144 
    145     ret = epoll_ctl(g_epollfd, EPOLL_CTL_ADD, fd, &event);
    146     if(ret < 0) {
    147         LOG_ERROR("epoll_ctl Add fd:%d error, Error:[%d:%s]", fd, errno, strerror(errno));
    148         return -1;
    149     }
    150 
    151     LOG_DEBUG("epoll add fd:%d--->%d success", fd, g_epollfd);
    152     return 0;    
    153 }
    154 
    155 int epollfd_init()
    156 {
    157     int epfd;
    158 
    159     /* create epoll fd */
    160     epfd = epoll_create(EPOLL_LISTEN_CNT); 
    161     if (epfd < 0) {
    162         LOG_ERROR("epoll_create error, Error:[%d:%s]", errno, strerror(errno));
    163         return -1;
    164     }
    165     g_epollfd = epfd;
    166     LOG_DEBUG("epoll fd:%d create success", epfd);
    167 
    168     return epfd;
    169 }
    170 
    171 int timerfd_init()
    172 {
    173     int tmfd;
    174     int ret;
    175     struct itimerspec new_value;
    176 
    177     new_value.it_value.tv_sec = 2;
    178     new_value.it_value.tv_nsec = 0;
    179     new_value.it_interval.tv_sec = 1;
    180     new_value.it_interval.tv_nsec = 0;
    181     
    182     tmfd = timerfd_create(CLOCK_MONOTONIC, 0);
    183     if (tmfd < 0) {
    184         LOG_ERROR("timerfd_create error, Error:[%d:%s]", errno, strerror(errno));
    185         return -1;
    186     }
    187 
    188     ret = timerfd_settime(tmfd, 0, &new_value, NULL);
    189     if (ret < 0) {
    190         LOG_ERROR("timerfd_settime error, Error:[%d:%s]", errno, strerror(errno));
    191         close(tmfd);
    192         return -1;
    193     }
    194 
    195     if (epoll_add_fd(tmfd)) {
    196         close(tmfd);
    197         return -1;
    198     }
    199     g_timerfd = tmfd;
    200 
    201     return 0;
    202 }
    203 
    204 int main(int argc, char **argv)
    205 {
    206     if (epollfd_init() < 0) {
    207         return -1;
    208     }
    209 
    210     if (timerfd_init()) {
    211         return -1;
    212     }
    213 
    214     /* event handle */
    215     epoll_event_handle();
    216 
    217     return 0;
    218 }

    参考资料:

    http://www.man7.org/linux/man-pages/man2/timerfd_create.2.html

    http://blog.csdn.net/walkingman321/article/details/6162055

  • 相关阅读:
    闽江学院2015-2016学年下学期《软件测试》课程-第五次博客作业
    在Swift中应用Grand Central Dispatch(下)
    在Swift中应用Grand Central Dispatch(上)转载自的goldenfiredo001的博客
    Asp.net mvc 框架揭秘之Asp.net +Mvc简介
    JavaScript数组
    网页校验
    删除弹出提示框_MVC
    业务体会
    判断数组值是否有重复
    sql
  • 原文地址:https://www.cnblogs.com/wenqiang/p/6698371.html
Copyright © 2020-2023  润新知