Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何正确使用timerfd?_C_Linux_Timer_Zeromq - Fatal编程技术网

C 如何正确使用timerfd?

C 如何正确使用timerfd?,c,linux,timer,zeromq,C,Linux,Timer,Zeromq,我将timerfd与zmq一起使用 如何使用timerfd\u create和timerfd\u set等待计时器()一秒钟 我已经浏览了这个链接,但是我仍然不知道如何初始化一个计时器,该计时器通过create和set每滴答一秒钟等待一次。这正是我的任务: 我们用timerfd\u create()启动一个计时器,即1/秒。滴答声。使用计时器设置计时器时\u set(..)a 计数器只是简单地递增,每次滴答声都会递减。当计数器达到0时,计时器 已经过期了 在这个项目中,我们有一个函数timer\

我将
timerfd
与zmq一起使用

如何使用
timerfd\u create
timerfd\u set
等待计时器()一秒钟

我已经浏览了这个链接,但是我仍然不知道如何初始化一个计时器,该计时器通过create和set每滴答一秒钟等待一次。这正是我的任务:

我们用
timerfd\u create()
启动一个计时器,即1/秒。滴答声。使用计时器设置计时器时
\u set(..)
a 计数器只是简单地递增,每次滴答声都会递减。当计数器达到0时,计时器 已经过期了

在这个项目中,我们有一个函数timer
\uuset()
,其中定时器是用函数timerfd\u create和
timerfd\u settimer()设置的。我希望你能帮助我

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


使用timerfds时,fd上的读取将返回计时器已过期的次数

timerfd\u设置时间(2)手册页:

在计时器文件描述符上操作 timerfd_create()返回的文件描述符支持以下操作:

读(2) 如果计时器自上次使用修改其设置以来已过期一次或多次 timerfd_settime(),或自上次成功读取(2)后,指定给读取(2)的缓冲区返回 包含已发生过期次数的无符号8字节整数(uint64_t)

如果在读取(2)时没有发生计时器过期,则调用会被阻塞 直到下一个计时器过期,或者如果文件描述符已被删除,则失败并显示错误EAGAIN 非阻塞(通过使用fcntl(2)F_设置FL操作设置O_非阻塞标志)

因此,基本上,创建一个无符号8字节整数(Linux上为uint64_t),并将其传递给read调用

uint64_t buf;
int expired = read( g_items[n].fd, &buf, sizeof(uint64_t));
if( expired < 0 ) perror("read");
uint64\u t buf;
int expired=read(g_items[n].fd,&buf,sizeof(uint64_t));
如果(过期<0)或(“读取”);

类似于此,如果您想阻止,直到到期。

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

使用设置

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\u值
)。但是你也设定了一个1的周期间隔,你没有提到要这么做的意愿


关于暂停 本手册的以下章节描述了这种行为:

int-timerfd\u创建(int-clockid,int-flags)

新值。它指定计时器的初始到期时间,以秒和纳秒为单位。将
new\u value的任一字段设置为非零值将启用计时器。
new\u value的两个字段设置为零将禁用计时器。

新值的一个或两个字段设置为非零值。它将
设置为非零值,以秒和纳秒为单位指定初始过期后重复计时器过期的周期如果
new\u value.it\u interval
的两个字段均为零,则计时器仅在
new\u value.it\u value
指定的时间过期一次

最后一段的重点是我的,因为它显示了如何使用单次计时器


timerrfd
的好处。如何检测计时器过期?
timerfd
提供的主要优点是计时器与文件描述符相关联,这意味着它

可由和监控

关于
read()
的另一个答案中包含的信息也是有效的:我们只需说,即使使用
select()
等函数,也需要
read()
函数来使用文件描述符中的数据


一个完整的例子 在下面的演示程序中,设置了4秒的超时;之后,设置5秒的周期间隔

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

请注意:

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

为什么在select中执行tfd+1?初始超时时间仅适用于第一次运行,之后计时器将计算间隔超时的时间?@zongul67您可以传递到
select
多个描述符。根据设计,该参数必须包含最大fd+1(在本例中为
tfd+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;
#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)