# 定时器timerfd 相关函数
#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

timerfd_create()创建一个定时器描述付timerfd
clockidCLOCK_REALTIME、CLOCK_MONOTONIC
flags为 0 或者 O_NONBLOCK
CLOCK_REALTIME  //自1970-01-01起经历的秒数、本秒中经历的纳秒数
CLOCK_MONOTONIC //自CPU启动时流逝的时间

timetfd_settime

timerfd_settime用来启动或关闭fd指定的定时器
fdtimerfd_create函数返回的定时器文件描述符
flags1 代表绝对时间,0 为相对时间
new_value指定新的超时时间
old_value不为 NULL,则返回定时器这这次设置之前的超时时间

timerfd_gettime

timerfd_gettime这个函数通常是为了检查定时器还有多长时间触发,或者检查定时器是否是一次性的还是周期性的。周期性定时器的it_interval会被设置为非零值,表示每次到期后,定时器会自动重新设置为这个间隔值。如果it_interval为零,则定时器只触发一次。

示例程序

#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 { printf(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))
   {
	   ssize_t s;
	   printf("%s %d\n",__FUNCTION__, __LINE__);
	   if ((argc != 2) && (argc != 4))
	   {
		   fprintf(stderr, "%s init-secs [interval-secs max-exp]\n", argv[0]);
		   handle_error("argc argv is error");
	   }
   }

   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);

}