Linux timerfd

  • timerfd是Linux提供的一个纳秒级的定时器文件,利用文件描述符fd操作

  • 系统调用:

    #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);
    
  • timerfd_create创建一个timer对象并返回fd,失败返回-1

    • clockid

      CLOCK_REALTIME
             一个可设置的全系统实时时钟。		
      CLOCK_MONOTONIC
             从系统启动后不被改变的时钟
      CLOCK_BOOTTIME (Since Linux 3.15)
             和CLOCK_MONOTONIC类似。然而,CLOCK_MONOTONIC时钟并不测量当系统挂起时的时间,CLOCK_BOOTTIME时钟执行包括系统暂停的时间。			
      CLOCK_REALTIME_ALARM (since Linux 3.11)
             类似于CLOCK_REALTIME,但是将会唤醒挂起的系统。			
      CLOCK_BOOTTIME_ALARM (since Linux 3.11)
      	   类似于CLOCK_BOOTTIME,但是将会唤醒挂起的系统。	
      
    • flags

      • TFD_NONBLOCK 非阻塞
      • TFD_CLOEXEC
  • timerfd_settime启动或关闭 fd 对应的定时器,成功返回0,失败返回-1,并存储错误码到errno。new_value设置第一次超时时间和之后的超时周期。old_value如果不为NULL,则用来存储当前时间。

    • itimerspec

      struct timespec {
          time_t tv_sec;                /* Seconds */
          long   tv_nsec;               /* Nanoseconds */
      };
      
      struct itimerspec {
          struct timespec it_interval;  /* 超时周期 */
          struct timespec it_value;     /* 初始超时时间 */
      };
      
    • flags

      • 0 相对时间
      • TFD_TIMER_ABSTIME 绝对时间
  • timerfd_gettime获得定时器距离下次超时还剩下的时间,成功返回0,失败返回-1,并存储错误码到errno。如果调用时定时器已经到期且it_interval不为0,调用此函数之后定时器重新开始计时。

  • 示例

       #include <sys/timerfd.h>
       #include <time.h>
       #include <unistd.h>
       #include <stdlib.h>
       #include <stdio.h>
       #include <stdint.h>        /* Definition of uint64_t */
    
       #define handle_error(msg) \
               do { perror(msg); exit(EXIT_FAILURE); } while (0)
    
       static void
       print_elapsed_time(void)
       {
           static struct timespec start;
           struct timespec curr;
           static int first_call = 1;
           int secs, nsecs;
    
           if (first_call) {
               first_call = 0;
               if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
                   handle_error("clock_gettime");
           }
    
           if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)
               handle_error("clock_gettime");
    
           secs = curr.tv_sec - start.tv_sec;
           nsecs = curr.tv_nsec - start.tv_nsec;
           if (nsecs < 0) {
               secs--;
               nsecs += 1000000000;
           }
           printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000);
       }
    
       int
       main(int argc, char *argv[])
       {
           struct itimerspec new_value;
           int max_exp, fd;
           struct timespec now;
           uint64_t exp, tot_exp;
           ssize_t s;
    
           if ((argc != 2) && (argc != 4)) {
               fprintf(stderr, "%s init-secs [interval-secs max-exp]\n",
                       argv[0]);
               exit(EXIT_FAILURE);
           }
    
           if (clock_gettime(CLOCK_REALTIME, &now) == -1)
               handle_error("clock_gettime");
    
           /* Create a CLOCK_REALTIME absolute timer with initial
              expiration and interval as specified in command line */
    
           new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]);
           new_value.it_value.tv_nsec = now.tv_nsec;
           if (argc == 2) {
               new_value.it_interval.tv_sec = 0;
               max_exp = 1;
           } else {
               new_value.it_interval.tv_sec = atoi(argv[2]);
               max_exp = atoi(argv[3]);
           }
           new_value.it_interval.tv_nsec = 0;
    
           fd = timerfd_create(CLOCK_REALTIME, 0);
           if (fd == -1)
               handle_error("timerfd_create");
    
           if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
               handle_error("timerfd_settime");
    
           print_elapsed_time();
           printf("timer started\n");
    
           for (tot_exp = 0; tot_exp < max_exp;) {
               s = read(fd, &exp, sizeof(uint64_t));
               if (s != sizeof(uint64_t))
                   handle_error("read");
    
               tot_exp += exp;
               print_elapsed_time();
               printf("read: %llu; total=%llu\n",
                       (unsigned long long) exp,
                       (unsigned long long) tot_exp);
           }
    
           exit(EXIT_SUCCESS);
       }
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

money的大雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值