使用 timerfd_create() 和 timerfd_settime() 的计时器不断到期,即使间隔设置为零

timer using timerfd_create() and timerfd_settime() continually expires even though interval is set to zero

这是精简代码。计时器超时(由 epoll_wait 报告)但即使间隔设置为零,epoll_wait 仍会持续触发计时器 fd 的准备就绪事件 (EPOLLIN)。 interval设置为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);

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