【问题标题】:Why is my timer not periodic but expired only one time?为什么我的计时器不是周期性的,而是只过期一次?
【发布时间】:2014-09-12 08:44:03
【问题描述】:

我使用 POSIX timerfd 函数创建了一个计时器。 意图是,计时器应该是周期性的,并且计时器到期从一个名为myFunc( )的单独函数中观察到

我多次调用此函数,以便在等待 5 秒后定期观察计时器到期。

问题是,一旦第一次在 5 秒后过期,下一次......它不会再次过期,即从第二次迭代开始没有观察到 5 秒的延迟。

谁能告诉我我错过了什么?

#include <stdio.h>
#include <iostream>
#include <errno.h>
#include <dlfcn.h>
#include <assert.h>
#include <sys/mman.h>
#include <new>

#include <limits.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>

using namespace std;

struct epoll_event event;
int timer_fd, efd, no_of_fd;
void myFunc( int i );

int main()
{
  struct itimerspec its;

  its.it_value.tv_sec = 5;
  its.it_value.tv_nsec = 0;

  its.it_interval.tv_sec = 3; // Every 3 seconds interval
  its.it_interval.tv_nsec = 0;


  efd = epoll_create(2);
  timer_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);

  if ( timer_fd == -1 )
  {
    fprintf(stderr, "timerfd_create error in start timer");
    return 1;
  }

  event.data.fd = timer_fd;
  event.events = EPOLLIN|EPOLLPRI;

  if ( epoll_ctl(efd, EPOLL_CTL_ADD, timer_fd, &event) == -1 )
  {
     fprintf(stderr, "epoll_ctl error in start timer"); 
     return 1;
  }

  if ( timerfd_settime(timer_fd, 0, &its, NULL) == -1 )
  {
    fprintf(stderr, "timerfd_settime error in start timer");
    return 1;
  }
  myFunc( 10 );
  myFunc( 20 );
  myFunc( 30 );
}

void myFunc( int i )
{
  printf("Inside myFunc %d\n", i);
  no_of_fd = 0;
  struct epoll_event revent;
  errno = 0;
  do {
     no_of_fd = epoll_wait(efd, &revent, 1, -1);
  } while ( no_of_fd < 0 && errno == EINTR );

  if ( no_of_fd < 0 )
  {
    fprintf(stderr, "epoll_wait error in start timer");

  }

  if ( revent.data.fd == timer_fd ) {
     printf("Timer expired \n");    
  }

}

【问题讨论】:

  • 好的,我有一个使用 Edge 触发机制的小解决方法,即我使用:event.events = EPOLLIN|EPOLLPRI|EPOLLET; 并且每次发生超时时我都需要读取文件描述符,并且它是经常性的。但是不能使用级别触发机制吗?
  • 好的,我得到了解决方案:它也适用于触发级别,并且只要我读取每次生成的数据,它就会反复出现。任何人都有任何线索,每次应该读取多少字节或者读取的最小字节数是多少才能正常工作?

标签: linux timer


【解决方案1】:

epoll 与电平触发一起使用时,您应该在每个 EPOLLIN 上读取 8 个字节。这是一个 int64,它告诉您事件到期的次数。读取它可以有效地“清除”这个数字,以便下一个 EPOLLIN 是不同事件到期的结果。

手册告诉你阅读:

          If the timer has already expired one or more times since its
          settings were last modified using timerfd_settime(), or since
          the last successful read(2), then the buffer given to read(2)
          returns an unsigned 8-byte integer (uint64_t) containing the
          number of expirations that have occurred.  (The returned value
          is in host byte order—that is, the native byte order for
          integers on the host machine.)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    • 1970-01-01
    • 2010-12-15
    相关资源
    最近更新 更多