本文共 2451 字,大约阅读时间需要 8 分钟。
timerfd 是 Linux 提供的一种定时器机制,基于文件描述符,具有高精度,定时器的精度最高可达纳秒级别。其 API 接口包括定时器的创建、启动、关闭和删除等功能。
定时器的创建可以通过 timerfd_create
函数实现。该函数接收两个参数:clockid
和 flags
。clockid
可以是 CLOCK_REALTIME
(实时时钟)或 CLOCK_MONOTONIC
(递增时钟)。实时时钟可能受系统时间的影响,而递增时钟则不会。flags
可选参数包括 TFD_NONBLOCK
(非阻塞)和 TFD_CLOEXEC
。使用非阻塞模式时,定时器的读操作不会阻塞,直到定时器超时为止。
定时器的启动和关闭可以通过 timerfd_settime
函数实现。该函数接收四个参数:fd
(定时器描述符)、flags
(0 或 TFD_TIMER_ABSTIME
),new_value
(新的超时值),以及可选的 old_value
(用于存储当前时间)。如果 new_value.it_value
为 0,则表示停止定时器。如果 new_value.it_interval
为 0,则表示定时器只会触发一次。
定时器与其他文件描述符一样,使用 close
函数释放其资源。注意,在使用定时器之前,应确保其已被正确关闭,以避免资源泄漏。
定时器相关的时间结构体包括 struct timespec
和 struct itimerspec
。struct timespec
包含 tv_sec
(秒)和 tv_nsec
(纳秒)两个成员,用于表示时间。struct itimerspec
包含 it_interval
(间隔时间)和 it_value
(初始超时时间)两个成员。
以下是一个结合epoll使用的定时器示例。该示例创建一个每隔 2 秒超时的定时器,并将其添加到epoll监听队列中。每当定时器超时时,epoll会触发读事件,随后可以执行相应的定时器回调函数。
#include#include #include #include #include #include #define TIME_MAX 2 int main() { int tfd; int efd; uint64_t value; struct epoll_event ev, *evptr; struct itimerspec time_intv; // 创建定时器 tfd = timerfd_create(CLOCK_MONOTONIC, 0); if (tfd == -1) { printf("create timer fd fail\n"); return -1; } // 设置定时器时间 time_intv.it_value.tv_sec = TIME_MAX; time_intv.it_value.tv_nsec = 0; time_intv.it_interval.tv_sec = time_intv.it_value.tv_sec; time_intv.it_interval.tv_nsec = time_intv.it_value.tv_nsec; // 启动定时器 if (timerfd_settime(tfd, 0, &time_intv, NULL) == -1) { printf("set timer time fail\n"); return -1; } // 创建epoll实例 efd = epoll_create1(0); if (efd == -1) { printf("create epoll fail\n"); close(tfd); return -1; } // 准备事件 evptr = (struct epoll_event *)malloc(sizeof(struct epoll_event)); if (!evptr) { printf("epoll event malloc fail\n"); close(tfd); close(efd); return -1; } ev.data.fd = tfd; ev.events = EPOLLIN; // 将定时器添加到epoll队列中 if (epoll_ctl(efd, EPOLL_CTL_ADD, tfd, &ev) == -1) { printf("epoll add fail\n"); close(tfd); close(efd); return -1; } // 等待事件 while (1) { int ret = epoll_wait(efd, evptr, 1, -1); if (ret == -1) { printf("epoll wait fail\n"); break; } if (evptr[0].events & EPOLLIN) { ret = read(evptr[0].data.fd, &value, sizeof(uint64_t)); if (ret == -1) { printf("read return -1, errno: %d\n", errno); } else { printf("*** timer up ***\n"); } } } // 释放资源 free(evptr); close(tfd); close(efd); return 0; }
该示例通过epoll监听定时器的读事件,当定时器超时时,epoll会触发相应的事件,随后可以执行定时器回调函数。
转载地址:http://pbgfk.baihongyu.com/