使用 epoll 时 timerfd 将无法读取
timerfd won't be ready to read when using 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时,效果很好。每一秒都会打印 "ding"。但是加入epoll观察timerfd时,progrom会一直阻塞在epoll_wait。
我试过使用 EPOLLET,但注意到发生了变化。这段代码有什么问题?
您的 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;
我打算使用 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时,效果很好。每一秒都会打印 "ding"。但是加入epoll观察timerfd时,progrom会一直阻塞在epoll_wait。 我试过使用 EPOLLET,但注意到发生了变化。这段代码有什么问题?
您的 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;