4

需要每 X(比如说 5)秒调用一个函数,下面的代码就是这样做的。

但它阻止了代码的执行。正如我希望它像 一样工作setitimer(),我可以(例如)每 5 秒调用一次函数并执行其他操作。

   #include <sys/timerfd.h>
   #include <time.h>
   #include <unistd.h>
   #include <stdlib.h>
   #include <stdio.h>
   #include <stdint.h>        /* Definition of uint64_t */

   #define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

   int
   main(int argc, char *argv[])
   {
       struct itimerspec new_value;
       int max_exp, fd;
       struct timespec now;
       uint64_t exp, tot_exp;
       ssize_t s;

       if (clock_gettime(CLOCK_REALTIME, &now) == -1)
           handle_error("clock_gettime");

       /* Create a CLOCK_REALTIME absolute timer with initial
          expiration and interval as specified in command line */

       new_value.it_value.tv_sec = now.tv_sec + 1; 
       new_value.it_value.tv_nsec = now.tv_nsec;

       new_value.it_interval.tv_sec = 5;
       new_value.it_interval.tv_nsec = 0;
       max_exp = 5; //say 5 times

       fd = timerfd_create(CLOCK_REALTIME, 0);
       if (fd == -1)
           handle_error("timerfd_create");

       if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
           handle_error("timerfd_settime");

       printf("timer started\n");
       for (tot_exp = 0; tot_exp < max_exp;) {
           s = read(fd, &exp, sizeof(uint64_t));
           if (s != sizeof(uint64_t))
               handle_error("read");

           tot_exp += exp;
           printf("read: %llu; total=%llu\n",
                   (unsigned long long) exp,
                   (unsigned long long) tot_exp);
       }
    //Do something else ?
    //while(1);
       exit(EXIT_SUCCESS);
   }

编辑 我还有一个问题。在将上述代码中的这些行从

   new_value.it_interval.tv_sec = 5;
   new_value.it_interval.tv_nsec = 0;

   new_value.it_interval.tv_sec = 0;
   new_value.it_interval.tv_nsec = 5000000000;

我看到没有 5 秒的延迟。这里发生了什么事?

4

2 回答 2

2

您需要了解如何使用多路复用系统调用,如poll(2)(或较旧的,往往会变得过时),并在使用它们之前测试timerfd_create(2)select(2)获得的文件描述符的可读性。read(2)

但是,请注意,timerfd_create仅当该read调用成功时才有效。因此,只有当poll您说 fd 不可读时,您才能执行其他操作。其他东西应该很快(持续不到 5 秒)。

您可能想研究事件循环库,例如libevent(包装poll)。如果您正在编写图形应用程序(使用 Qt 或 Gtk),它确实已经有自己的事件循环。如果足够聪明,你可以在没有任何 5 秒的情况下完成你的 5 秒时间timerfd_create,只需通过你的事件循环(通过仔细设置给定的超时poll等)。

附加物:

tv_nsec字段应始终为非负数且小于 1000000000(一秒内的纳秒数)。

于 2012-09-19T16:48:05.143 回答
0

你有什么理由必须使用timerfd?只需安排一个警报并为 SIGALRM 创建一个处理程序来调用您的函数。

如果您不想使用信号,只需创建一个额外的线程来阻塞您的计时器 fd 并在主线程中正常进行。

如果您不喜欢其中任何一个,并且想在等待时工作,则必须进行投票。您可以按照 basile 的建议进行操作,或者您可以只存储当前时间并检查何时进行轮询以查看所需的时间段是否已过。

于 2012-09-19T17:00:25.943 回答