Почему мой таймер не периодический, а истек только один раз?

Я создал таймер, используя функцию 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");    
  }

}

person RajSanpui    schedule 12.09.2014    source источник
comment
Хорошо, у меня есть небольшой обходной путь, использующий механизм запуска Edge, то есть я использую: event.events = EPOLLIN|EPOLLPRI|EPOLLET; и каждый раз, когда мне нужно читать дескриптор файла всякий раз, когда происходит тайм-аут, и он повторяется. Но нельзя ли его использовать с помощью триггерного механизма уровня?   -  person RajSanpui    schedule 12.09.2014
comment
Хорошо, я получил решение: он также работает с запуском уровня, и при условии, что я читаю данные, создаваемые каждый раз, он повторяется. Кто-нибудь знает, сколько байтов нужно читать каждый раз или каково минимальное количество байтов для чтения, чтобы оно работало?   -  person RajSanpui    schedule 12.09.2014


Ответы (1)


При использовании epoll с запуском по уровню вы должны считывать 8 байтов для каждого EPOLLIN. Это 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.)
person haelix    schedule 14.10.2014