在使用epoll时,timerfd不准备阅读

时间:2017-01-12 02:34:54

标签: c linux timer epoll

我打算使用epoll查看timerfd并触发一些操作。 代码是打击:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/timerfd.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/epoll.h>

int main(int argc, char const *argv[])
{
    struct timespec now;
    clock_gettime(CLOCK_MONOTONIC, &now);
    int timerfd;
    timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
    struct itimerspec new_value;
    new_value.it_value.tv_sec = 1;
    new_value.it_interval.tv_sec = 1;
    timerfd_settime(timerfd, 0, &new_value, NULL);
    // uint64_t buff;
    // while(true) {
    //  read(timerfd, &buff, sizeof(uint64_t));
    //  printf("%s\n", "ding");
    // }

    // code above works fine.

    struct epoll_event ev, events[10];
    int epollfd;
    epollfd = epoll_create1(0);
    if (epollfd == -1) {
       perror("epoll_create1");
       exit(EXIT_FAILURE);
    }
    ev.events = EPOLLIN;
    ev.data.fd = timerfd;

    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev) == -1) {
        perror("epoll_ctl: timerfd");
        exit(EXIT_FAILURE);
    }
    int num;
    printf("start\n");
    while(true) {
        num = epoll_wait(epollfd, events, 10, -1);
        printf("%d\n", num);
        uint64_t buff;
        read(timerfd, &buff, sizeof(uint64_t));
        printf("%s\n", "ding");
    }
    return 0;
}

单独使用timerfd时,它可以正常工作。每一秒都会印刷&#34; ding&#34;。但是当添加epoll来观察timerfd时,progrom将永远阻塞在epoll_wait。 我尝试使用EPOLLET,但注意到了改变。这段代码有什么问题?

1 个答案:

答案 0 :(得分:3)

您的itimerspec未正确初始化,因此根据其中包含的特定垃圾值,timerfd_settime()可能会失败。要检测到这一点,请执行错误检查:

if (timerfd_settime(timerfd, 0, &new_value, NULL) != 0) {
      perror("settime");
      exit(-1);
}

调试此方法的另一种方法是在strace程序下运行程序,您将看到哪些系统调用失败。

相关结构如下:

struct timespec {
   time_t tv_sec;
   long   tv_nsec;
 };

struct itimerspec {
   struct timespec it_interval;  
   struct timespec it_value;  
};

您必须完全初始化这两个成员,并且您的程序将可靠地运行:

new_value.it_value.tv_sec = 1;
new_value.it_value.tv_nsec = 0;
new_value.it_interval.tv_sec = 1;
new_value.it_interval.tv_nsec = 0;