【问题标题】:timer using timerfd_create() and timerfd_settime() continually expires even though interval is set to zero即使间隔设置为零,使用 timerfd_create() 和 timerfd_settime() 的计时器也会持续到期
【发布时间】:2020-02-28 19:49:43
【问题描述】:

这是精简后的代码。计时器及时到期(由 epoll_wait 报告),但即使间隔设置为零,epoll_wait 也会持续为计时器 fd 触发准备读取事件 (EPOLLIN)。间隔设置为0,不应该只触发一次吗?

timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
struct itimerspec *my_itimerspec_new, *my_itimerspec_old;
my_itimerspec_new = malloc(sizeof(struct itimerspec));
my_itimerspec_old = malloc(sizeof(struct itimerspec));

bzero(my_itimerspec_new, sizeof(struct itimerspec));
bzero(my_itimerspec_old, sizeof(struct itimerspec));


my_itimerspec_new->it_value.tv_sec  = 60;
my_itimerspec_new->it_value.tv_nsec = 0; 
my_itimerspec_new->it_interval.tv_sec  = 0; 
my_itimerspec_new->it_interval.tv_nsec = 0; 

my_itimerspec_old->it_value.tv_sec  = 0; 
my_itimerspec_old->it_value.tv_nsec = 0; 
my_itimerspec_old->it_interval.tv_sec  = 0; 
my_itimerspec_old->it_interval.tv_nsec = 0; 

timerfd_settime(timerFd, 0, my_itimerspec_new, my_itimerspec_old);

【问题讨论】:

  • 你读过计时器吗?需要minimal reproducible example
  • 你为什么使用malloc?据我所知,没有必要。无论如何,看看 this 部分代码,计时器确实应该只过期一次。所以你应该写一个minimal reproducible example
  • @hyde 我已经简化了更大应用程序的代码。这里不需要malloc。我发现了问题......正如肖恩指出的那样,我没有阅读计时器。我认为使用 EPOLLET 是不需要的。当然,在生产代码中,我必须阅读并检查触发 Epoll_wait 循环的原因。使用 EPOLLET 和 EPOLLONESHOT 时,是否应该在读取后重新武装直到返回 EAGAIN ,在读取之前还是没有关系?可能这应该是一个新问题。
  • @Shawn 你的问题是正确的!问题已解决。相关问题:在使用EPOLLET和EPOLLONESHOT时,是应该在读取后直到返回EAGAIN,在读取之前再重新装弹还是没关系?
  • @Shawn 如果您发表评论作为答案,我会接受。

标签: linux timer epoll


【解决方案1】:

epollpoll()select() 等会告诉你计时器描述符是否可以在没有阻塞的情况下读取。它在计时器到期时变为可读并一直保持到您read() 从中获取一个 64 位无符号整数,其中包含自上次读取以来计时器到期的次数。如果您不这样做,它会继续以可读方式进行轮询(但是,如果您使用 ET 和 ONESHOT 选项,则模数会影响行为)

【讨论】:

    猜你喜欢
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多