出现有关正确设置计时器超时的问题。
通过设置
timerValue.it_value.tv_sec = 1;
timerValue.it_value.tv_nsec = 0;
timerValue.it_interval.tv_sec = 1;
timerValue.it_interval.tv_nsec = 0;
您正确地将 初始超时 设置为 1 秒(字段 timerValue.it_value)。但是你也设置了一个周期性的间隔 1s,你没有提到这样做的意愿。
关于超时
手册的以下段落描述了此行为:
int timerfd_create(int clockid, int flags);
new_value.it_value 指定计时器的初始到期时间,以秒和纳秒为单位。将new_value.it_value 的任一字段设置为非零值会启用计时器。
将new_value.it_value 的两个字段设置为零会禁用计时器。
将new_value.it_interval 的一个或两个字段设置为非零值指定初始到期后重复计时器到期的时间段(以秒和纳秒为单位)。 如果new_value.it_interval 的两个字段都为零,则计时器仅在new_value.it_value 指定的时间到期一次。
最后一段的重点是我的,因为它说明了如何做才能有一个单次计时器。
timerrfd 的好处。如何检测定时器到期?
timerfd 提供的主要优点是计时器与文件描述符相关联,这意味着它
可由select(2)、poll(2) 和epoll(7) 监控。
关于read() 的其他答案中包含的信息也是有效的:我们只是说,即使使用诸如select()、read() 之类的函数也需要使用文件描述符中的数据。
一个完整的例子
在下面的演示程序中,设置了 4 秒的超时时间;之后设置 5 秒的周期性间隔。
旧的select()用于等待定时器到期,read()用于消费数据(即过期超时的次数;我们将忽略它)。
#include <stdio.h>
#include <sys/timerfd.h>
#include <sys/select.h>
#include <time.h>
int main()
{
int tfd = timerfd_create(CLOCK_REALTIME, 0);
printf("Starting at (%d)...\n", (int)time(NULL));
if(tfd > 0)
{
char dummybuf[8];
struct itimerspec spec =
{
{ 5, 0 }, // Set to {0, 0} if you need a one-shot timer
{ 4, 0 }
};
timerfd_settime(tfd, 0, &spec, NULL);
/* Wait */
fd_set rfds;
int retval;
/* Watch timefd file descriptor */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
FD_SET(tfd, &rfds);
/* Let's wait for initial timer expiration */
retval = select(tfd+1, &rfds, NULL, NULL, NULL); /* Last parameter = NULL --> wait forever */
printf("Expired at %d! (%d) (%d)\n", (int)time(NULL), retval, read(tfd, dummybuf, 8) );
/* Let's wait for initial timer expiration */
retval = select(tfd+1, &rfds, NULL, NULL, NULL);
printf("Expired at %d! (%d) (%d)\n", (int)time(NULL), retval, read(tfd, dummybuf, 8) );
retval = select(tfd+1, &rfds, NULL, NULL, NULL);
printf("Expired at %d! (%d) (%d)\n", (int)time(NULL), retval, read(tfd, dummybuf, 8) );
}
return 0;
}
这是输出。每行还包含时间戳,因此可以检查实际经过的时间>
Starting at (1596547762)...
Expired at 1596547766! (1) (8)
Expired at 1596547771! (1) (8)
Expired at 1596547776! (1) (8)
请注意:
- 我们刚刚执行了 3 次读取,用于测试
- 间隔为 4s + 5s + 5s(初始超时 + 两次间隔超时)
-
read() 返回 8 个字节。我们忽略了它们,但它们包含过期超时的数量