首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何正确使用timerfd?

如何正确使用timerfd?
EN

Stack Overflow用户
提问于 2020-08-04 07:02:25
回答 2查看 5.4K关注 0票数 3

我在zmq中使用timerfd

如何使用timerfd_createtimerfd_set来等待定时器(https://man7.org/linux/man-pages/man2/timerfd_create.2.html)?

我已经查看了链接,但我仍然不知道如何初始化一个定时器,该定时器每个滴答等待1秒与创建和设置。这正是我的任务:

我们用timerfd_create()启动计时器,这是1/秒。滴答作响。当使用计时器_set_(..)设置计时器时,计数器就会简单地递增,并且随着滴答量的增加而减少。当计数器达到0时,计时器已过期。

在这个项目中,我们有一个函数计时器_ set _(),其中计时器是用函数timerfd_create和timerfd_settimer()设置的。我希望你能帮助我。

这是我的进步(我的代码的一部分):

代码语言:javascript
运行
复制
    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); 
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-08-04 13:34:29

出现有关正确设置计时器超时的问题。

通过设置

代码语言:javascript
运行
复制
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提供的主要优点是定时器与文件描述符相关联,这意味着它

可由select(2)poll(2)epoll(7)监控。

关于read()的另一个答案中包含的信息也是有效的:让我们简单地说,即使使用select()之类的函数,也需要read()函数才能使用文件描述符中的数据。

一个完整的例子

在下面的演示程序中,设置了4秒的超时;之后设置了5秒的周期间隔。

好的旧select()用于等待计时器过期,而read()用于使用数据(即过期超时的次数;我们将忽略它)。

代码语言:javascript
运行
复制
#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>。

代码语言:javascript
运行
复制
Starting at (1596547762)...
Expired at 1596547766! (1) (8)
Expired at 1596547771! (1) (8)
Expired at 1596547776! (1) (8)

请注意:

  • 我们刚刚执行了3次读取,对于测试
  • ,间隔为4s + 5s + 5s (初始超时+两个间隔超时)
  • 8字节由read()返回。我们忽略了它们,但是它们包含了过期的超时(

)的数量。

票数 4
EN

Stack Overflow用户

发布于 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),并将其传递给您的读取调用。

代码语言:javascript
运行
复制
uint64_t buf;
int expired = read( g_items[n].fd, &buf, sizeof(uint64_t));
if( expired < 0 ) perror("read");

类似的东西,如果你想阻止,直到你到期。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63241720

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档