我在zmq中使用timerfd
。
如何使用timerfd_create
和timerfd_set
来等待定时器(https://man7.org/linux/man-pages/man2/timerfd_create.2.html)?
我已经查看了链接,但我仍然不知道如何初始化一个定时器,该定时器每个滴答等待1秒与创建和设置。这正是我的任务:
我们用
timerfd_create()
启动计时器,这是1/秒。滴答作响。当使用计时器_set_(..)
设置计时器时,计数器就会简单地递增,并且随着滴答量的增加而减少。当计数器达到0时,计时器已过期。
在这个项目中,我们有一个函数计时器_ 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);
发布于 2020-08-04 13:34:29
出现有关正确设置计时器超时的问题。
通过设置
timerValue.it_value.tv_sec = 1;
timerValue.it_value.tv_nsec = 0;
timerValue.it_interval.tv_sec = 1;
timerValue.it_interval.tv_nsec = 0;
您正在正确地将初始超时设置为1s (字段timerValue.it_value
)。但是你也设定了1s的周期间隔,而你没有提到去做它的意愿。
关于暂停
手册的下面一段描述了这种行为:
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()
函数才能使用文件描述符中的数据。
一个完整的例子
在下面的演示程序中,设置了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 (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;
}
这是输出。每一行还包含时间戳,因此实际运行的时间可以是checked>。
Starting at (1596547762)...
Expired at 1596547766! (1) (8)
Expired at 1596547771! (1) (8)
Expired at 1596547776! (1) (8)
请注意:
read()
返回。我们忽略了它们,但是它们包含了过期的超时()的数量。
发布于 2020-08-04 08:56:05
对于timerfds,其思想是fd上的read将返回计时器过期的次数。
来自timerfd_settime(2)手册页:
对计时器文件描述符操作的
timerfd_create()返回的文件描述符支持以下操作:
读(2)如果计时器自上次使用timerfd_settime()修改其设置以来,或自上次成功读取(2)以来,计时器已过期一次或多次,则给读(2)的缓冲区返回一个无符号8字节整数(uint64_t),其中包含已发生的到期次数。如果在读取(2)时没有计时器到期,那么调用将一直阻塞直到下一个计时器到期,或者如果文件描述符已非阻塞(通过使用fcntl(2) F_SETFL操作来设置O_NONBLOCK标志),则使用错误EAGAIN失败。
因此,基本上,您创建一个无符号的8字节整数(Linux上的uint64_t),并将其传递给您的读取调用。
uint64_t buf;
int expired = read( g_items[n].fd, &buf, sizeof(uint64_t));
if( expired < 0 ) perror("read");
类似的东西,如果你想阻止,直到你到期。
https://stackoverflow.com/questions/63241720
复制相似问题