我与 zmq 一起使用timerfd。
如何使用计时器timerfd_create并timerfd_set等待一秒钟(https://man7.org/linux/man-pages/man2/timerfd_create.2.html)?
我已经浏览了链接,但我仍然不明白如何初始化一个计时器,该计时器在创建和设置时每滴答等待一秒。这正是我的任务:
我们用 启动一个计时器
timerfd_create(),即 1/秒。滴答作响。当使用计时器设置计时器时,_set_(..)计数器会简单地增加,而每次滴答都会减少。当计数器达到 0 时,计时器就到期了。
在这个项目中,我们有一个函数timer _ set _(),其中定时器是通过函数timerfd_create和设置的timerfd_settimer()。我希望你可以帮助我。
这是我的进度(我的代码的一部分):
struct itimerspec timerValue;
g_items[n].socket = nullptr;
g_items[n].events = ZMQ_POLLIN;
g_items[n].fd = timerfd_create(CLOCK_REALTIME, 0);
if(g_items[n].fd == -1 ){
printf("timerfd_create() failed: errno=%d\n", errno);
return -1;
}
timerValue.it_value.tv_sec = 1;
timerValue.it_value.tv_nsec = 0;
timerValue.it_interval.tv_sec = 1;
timerValue.it_interval.tv_nsec = 0;
timerfd_settime(g_items[n].fd, 0, &timerValue, NULL);
Run Code Online (Sandbox Code Playgroud)
出现有关正确设置计时器超时的问题。
随着设置
timerValue.it_value.tv_sec = 1;
timerValue.it_value.tv_nsec = 0;
timerValue.it_interval.tv_sec = 1;
timerValue.it_interval.tv_nsec = 0;
Run Code Online (Sandbox Code Playgroud)
您正确地将初始超时设置为 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是计时器与文件描述符相关联,这意味着它
另一个答案中包含的信息read()也是有效的:我们只是说,即使使用诸如 之类的函数select(),read()也需要 function 才能使用文件描述符中的数据。
在下面的演示程序中,设置了4秒的超时;之后设置 5 秒的周期间隔。
good oldselect()用于等待定时器到期,并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 (twice) for periodic 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;
}
Run Code Online (Sandbox Code Playgroud)
这是输出。每行还包含时间戳,以便可以检查实际经过的时间>
Starting at (1596547762)...
Expired at 1596547766! (1) (8)
Expired at 1596547771! (1) (8)
Expired at 1596547776! (1) (8)
Run Code Online (Sandbox Code Playgroud)
请注意:
read()。我们忽略了它们,但它们包含了过期超时的数量