Linux 使用timerfd_create()和timerfd_settime()的计时器持续过期,即使间隔设置为零

Linux 使用timerfd_create()和timerfd_settime()的计时器持续过期,即使间隔设置为零,linux,timer,epoll,Linux,Timer,Epoll,这是精简的代码。计时器在时间上过期(由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 = m

这是精简的代码。计时器在时间上过期(由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);

epoll
poll()
select()
等将告诉您计时器描述符是否可读且无阻塞。当计时器过期时,它将变得可读,并一直保持可读状态,直到您从中读取一个64位无符号整数,该整数包含自上次读取以来计时器过期的次数。如果您不这样做,它将继续以可读的方式轮询(但是,如果您正在使用这些选项,则模数ET和ONESHOT选项会影响行为)

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

您是否读取过计时器?需要说明为什么使用
malloc
?就我所知,没有必要。无论如何,看看这个部分代码,计时器应该只过期一次。因此,您应该编写一个@hyde,我已经简化了来自更大应用程序的代码。这里不需要malloc。我发现了问题。。。我没有像肖恩指出的那样看计时器。我认为EPOLLET不需要它。当然,在生产代码中,我必须阅读并检查是什么触发了Epoll_等待循环。当使用EPOLLET和EPOLOLONESHOT时,是否应在读取后重新装填,直到返回EAGAIN,然后再读取,还是不重要?也许这应该是一个新问题。@Shawn你的问题很正确!问题解决了。相关问题:当使用EPOLLET和EPOLLONESHOT时,是应该在阅读后重新装填,直到返回EAGAIN,还是在阅读前重新装填?Shawn如果你发表评论作为回答,我会接受。你读过计时器吗?需要说明为什么使用
malloc
?就我所知,没有必要。无论如何,看看这个部分代码,计时器应该只过期一次。因此,您应该编写一个@hyde,我已经简化了来自更大应用程序的代码。这里不需要malloc。我发现了问题。。。我没有像肖恩指出的那样看计时器。我认为EPOLLET不需要它。当然,在生产代码中,我必须阅读并检查是什么触发了Epoll_等待循环。当使用EPOLLET和EPOLOLONESHOT时,是否应在读取后重新装填,直到返回EAGAIN,然后再读取,还是不重要?也许这应该是一个新问题。@Shawn你的问题很正确!问题解决了。相关问题:当使用EPOLLET和Epolleneshot时,是应该在阅读后重新装填,直到返回EAGAIN,还是在阅读前重新装填?Shawn如果您将您的评论作为答案发布,我将接受。