-
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); }
Linux timerfd
最新推荐文章于 2024-01-23 09:43:14 发布