2014-10-10 2 views
1

Я использую таймер, используя timerfd. Это относительный таймер, который мне просто нужно повторять навсегда с той скоростью, на которую он установлен. Я хочу опросить это событие и изначально попытался использовать опрос. Когда я это сделал, я увижу событие таймера в первый раз, а затем больше никогда. Однако, когда я перешел на использование epoll (никаких изменений вообще не было в настройке timerfd), он работает так, как ожидалось.Повторяющееся событие timerfd работает с epoll, а не с опросом

Вот код с опросом:

#include <sys/timerfd.h> 
#include <sys/poll.h> 
#include <sys/epoll.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <strings.h> 
#include <unistd.h> 

int main(int ac, char *av[]) 
{ 
    struct pollfd p; 
    int timerfd; 
    struct itimerspec timerValue; 

    /* clear pollfd */ 
    bzero(&p, sizeof(p)); 

    /* set timerfd */ 
    timerfd = timerfd_create(CLOCK_REALTIME, 0); 
    if (timerfd < 0) { 
     printf("failed to create timer fd\n"); 
     exit(1); 
    } 
    bzero(&timerValue, sizeof(timerValue)); 
    timerValue.it_value.tv_sec = 1; 
    timerValue.it_value.tv_nsec = 0; 
    timerValue.it_interval.tv_sec = 1; 
    timerValue.it_interval.tv_nsec = 0; 

    /* set events */ 
    p.fd = timerfd; 
    p.revents = 0; 
    p.events = POLLIN; 

    /* start timer */ 
    if (timerfd_settime(timerfd, 0, &timerValue, NULL) < 0) { 
     printf("could not start timer\n"); 
     exit(1); 
    } 

    /* wait for events */ 
    while (1) { 
     int numEvents = poll(&p, 1, -1); 
     if (numEvents > 0) { 
      int timersElapsed = 0; 
      (void) read(p.fd, &timersElapsed, 8); 
      printf("timers elapsed: %d\n", timersElapsed); 
     } 
    } 

    exit(0); 
} 

А вот код с Epoll:

#include <sys/timerfd.h> 
#include <sys/poll.h> 
#include <sys/epoll.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <strings.h> 
#include <unistd.h> 

int main(int ac, char *av[]) 
{ 
    struct epoll_event epollEvent; 
    struct epoll_event newEvents; 
    int timerfd; 
    int epollfd; 
    struct itimerspec timerValue; 

    /* set timerfd */ 
    timerfd = timerfd_create(CLOCK_MONOTONIC, 0); 
    if (timerfd < 0) { 
     printf("failed to create timer fd\n"); 
     exit(1); 
    } 
    bzero(&timerValue, sizeof(timerValue)); 
    timerValue.it_value.tv_sec = 1; 
    timerValue.it_value.tv_nsec = 0; 
    timerValue.it_interval.tv_sec = 1; 
    timerValue.it_interval.tv_nsec = 0; 

    /* set events */ 
    epollfd = epoll_create1(0); 
    epollEvent.events = EPOLLIN; 
    epollEvent.data.fd = timerfd; 
    epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &epollEvent); 

    /* start timer */ 
    if (timerfd_settime(timerfd, 0, &timerValue, NULL) < 0) { 
     printf("could not start timer\n"); 
     exit(1); 
    } 

    /* wait for events */ 
    while (1) { 
     int numEvents = epoll_wait(epollfd, &newEvents, 1, 0); 
     if (numEvents > 0) { 
      int timersElapsed = 0; 
      (void) read(epollEvent.data.fd, &timersElapsed, 8); 
      printf("timers elapsed: %d\n", timersElapsed); 
     } 
    } 

    exit(0); 
} 

Любая идея, что я могу делать неправильно с опросом? Может быть, он не предназначен для использования таким образом с timerfd? Спасибо.

+0

Ваш код poll() отлично подходит для меня. Попробуйте найти что-нибудь подозрительное, когда вы запускаете код с помощью инструмента strace. – nos

+0

Я тоже пробовал ваше cdoe, и он отлично работает. Я запускал его на Linux 3.13. –

+0

@ nos - Я запускал свой код poll() с помощью strafe, и проблема в том, что дескриптор файла poll() меняется во втором вызове. Таким образом, первый вызов poll() вызывается, значение fd равно 3 (это было создано timer_createfd). Однако во второй раз, когда он вызывается, значение fd равно 0. 'poll ([{fd = 3, events = POLLIN}], 1, 4294967295) = 1 ([{fd = 3, revents = POLLIN}]). .. poll ([{fd = 0, events = POLLIN}], 1, 4294967295 ... блоки навсегда'. – budhe888

ответ

0

Это, похоже, проблема с Fedora (или моей установкой Fedora). В этой системе работает 3,16, а функция poll() не работает.

Однако, на отдельной установке Ubuntu с 3.13, код poll() выше работает просто отлично. Поскольку я буду использовать Ubuntu в будущем в любом случае, я не буду пытаться отслеживать проблему на Fedora. Хотя мне любопытно, если другие видят эту же проблему в системах Fedora.