【问题标题】:Why waiting indefinitely - timerfd_create? Where have i gone wrong?为什么无限期地等待 - timerfd_create?我哪里出错了?
【发布时间】:2011-05-20 10:27:52
【问题描述】:

我使用timerfd_create 创建了一个可以在 5 秒内到期的计时器,但我可以看到它无限期地等待。

有人可以帮我吗?

提前致谢。

这是我的代码:

enter code here
#include <sys/timerfd.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <time.h>

int main()
{
  struct itimerspec its;
  struct epoll_event event, revent;

  int timer_fd, efd;

  /* Setting timer interval */
  its.it_interval.tv_sec=1;
  its.it_interval.tv_nsec=0;

  /* Setting timer expiration */
  its.it_value.tv_sec=5;
  its.it_value.tv_nsec=0;

  efd=epoll_create(2);
  event.data.fd=timer_fd;

  event.events=EPOLLIN;
  epoll_ctl(efd, EPOLL_CTL_ADD, timer_fd, &event);

  timer_fd=timerfd_create(CLOCK_REALTIME, 0);

  if(timer_fd==-1)
  {
    perror("timerfd:");
  }

  if(timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &its, NULL)==-1)
  {
   perror("timerfd_settime error:");
  }

  printf("Starting the timer...");

  while(1) {
     epoll_wait(efd, &revent, 1, -1);
  }
}

【问题讨论】:

    标签: c linux timer


    【解决方案1】:

    颠倒调用epoll_ctltimerfd_create 的顺序。现在您正在向事件集添加一些随机整数值。

    编辑0:

    几点:

    • timerfd_create(2) 产生一个文件描述符,就像open(2)socket(2) 一样。您必须将返回值分配给timer_fd 变量之前 将它提供给epoll_ctl(2),否则它只是堆栈中的一个随机整数值。
    • 不要使用TFD_TIMER_ABSTIME - 您要求内核启动一个计时器,该计时器在Epoch 之后一秒到期(这没什么大不了的 - 它会立即到期)。
    • 当计时器到期时,epoll_wait(2) 返回就绪文件描述符的数量,在您的示例中为1,您应该处理它。另一方面,您只是忽略该返回值并在一个紧密的循环中旋转,因此您甚至不知道计时器即将到期。
    • 您需要从定时器文件描述符中读取来消耗过期事件。否则,所有对 epoll_wait(2) 的后续调用将立即返回,因为描述符仍处于“已发出信号”状态。
    • 始终检查系统调用的返回值并根据errno(3) 的值处理错误情况 - 每个调用的手册页都会为您提供可能的错误值。

    编辑 1:

    您确实希望围绕epoll_wait(2)(或select(2).或poll(2))进行循环,但您需要:

    1. 处理发出信号的 IO 事件(这就是这些多路复用 API 的重点 - 能够等待多个描述符并分派事件),并且
    2. 能够跳出该循环(在信号上、在来自专用文件描述符 ala self-pipe trick 的输入上或在某些应用程序事件上)。

    希望这会有所帮助。

    【讨论】:

    • 你的意思是先timerfd_create再epoll_ctl?如果这就是你的意思,那么对不起,它仍然不起作用。
    • 我已经找到了解决方案,但请告诉我是否有其他方法可以等待文件描述符而不是在紧的 while 循环中等待?
    • @Nikolai,很好的答案。我只想补充一点,而不是使用管道来表示循环结束,我会使用 eventfd[0],它比包含两个 FD 和管道数据结构的管道便宜:[0] man7.org/linux/man-pages/man2/eventfd.2.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 2019-07-12
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2016-08-02
    相关资源
    最近更新 更多