描述符相关的定时器是指可以通过描述符进行操作的一种定时器。
下面根据man pages提供的例子学习该定时器的具体应用。
主要头文件和函数有
#include <sys/timerfd.h>
int timerfd_create(int clockid, int flags);
clockid 可为CLOCK_MONOTONIC 或者 CLOCK_REALTIME;
CLOCK_REALTIME:真实时间类型,修改时钟会影响定时器;系统实时时间,随系统实时时间改变而改变,即从UTC1970-1-1 0:0:0开始计时;
CLOCK_MONOTONIC:相对时间类型,修改时钟不影响定时器;从系统启动这一刻起开始计时,不受系统时间被用户改变的影响 ;
int timerfd_settime(int fd, int flags,
const struct itimerspec *new_value,
struct itimerspec *old_value);
参数flags为TFD_TIMER_ABSTIME代表设置的是绝对时间;
为0代表相对时间。后面会举例子说明两者的区别。
int timerfd_gettime(int fd, struct itimerspec *curr_value);
代码例子:
#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"); //TFD_TIMER_ABSTIME 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); }
代码片段2:
两个程序的效果是一样,区别是 timerfd_settime() flag参数由TFD_TIMER_ABSTIME 改为 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 relative 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; new_value.it_value.tv_sec = atoi(argv[1]);//modify new_value.it_value.tv_nsec = 0;//modify 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"); //TFD_TIMER_ABSTIME modify to 0, relative timer if (timerfd_settime(fd, 0, &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); }
http://blog.csdn.net/sunlylorn/article/details/6313278
http://blog.csdn.net/chgaowei/article/details/21295811
http://blog.csdn.net/gdutliuyun827/article/details/8470777
http://www.kernel.org/doc/man-pages/.