select()不适合使用eventfd

我想使用eventfd来表示内核空间和用户空间之间的简单事件。 eventfd将用作信号的方式,实际数据将使用ioctl传输。 在继续实现这个之前,我写了一个简单的程序来看看eventfd如何与select()一起工作。 看来,如果你使用select来等待一个eventfd,当你在一个单独的线程中写入它时,它不会返回。 在我写的代码中,写入线程从程序启动开始等待5秒,然后写入到eventfd中两次。 我希望select()在写入之后立即返回到读线程中,但是这不会发生。 select()仅在10秒的超时后返回并返回零。 不pipe这个返回值为零,当我尝试在10秒后读取eventfd时,我会得到正确的值。

我使用Ubuntu 12.04.1(3.2.0-29-generic-pae)i386

任何想法,为什么这样呢? 在我看来,select()不工作,因为它应该。

PS:这个问题类似于linux – 不能让eventfd和epoll一起工作

有没有人面临类似的问题?

#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <stdint.h> //Definition of uint64_t #include <pthread.h> //One thread writes to fd, other waits on it and then reads it #include <time.h> //Writing thread uses delay before writing #include <sys/eventfd.h> int efd; //Event file descriptor void * writing_thread_func() { uint64_t eftd_ctr = 34; ssize_t s; printf("\n%s: now running...",__func__); printf("\n%s: now sleeping for 5 seconds...",__func__); fflush(stdout); //must call fflush before sleeping to ensure previous printf() is executed sleep(5); printf("\n%s: Writing %lld to eventfd...",__func__,eftd_ctr); s = write(efd, &eftd_ctr, sizeof(uint64_t)); if (s != sizeof(uint64_t)) { printf("\n%s: eventfd writing error. Exiting...",__func__); exit(EXIT_FAILURE); } eftd_ctr = 99; printf("\n%s: Writing %lld to eventfd...",__func__,eftd_ctr); s = write(efd, &eftd_ctr, sizeof(uint64_t)); if (s != sizeof(uint64_t)) { printf("\n%s: eventfd writing error. Exiting...",__func__); exit(EXIT_FAILURE); } printf("\n%s: thread exiting...",__func__); pthread_exit(0); } void * reading_thread_func() { ssize_t s; uint64_t eftd_ctr; int retval; //for select() fd_set rfds; //for select() struct timeval tv; //for select() printf("\n%s: now running...",__func__); printf("\n%s: now waiting on select()...",__func__); //Watch efd FD_ZERO(&rfds); FD_SET(efd, &rfds); //Wait up to 10 seconds tv.tv_sec = 10; tv.tv_usec = 0; retval = select(1, &rfds, NULL, NULL, &tv); if (retval == -1){ printf("\n%s: select() error. Exiting...",__func__); exit(EXIT_FAILURE); } else if (retval > 0) { printf("\n%s: select() says data is available now. Exiting...",__func__); printf("\n%s: returned from select(), now executing read()...",__func__); s = read(efd, &eftd_ctr, sizeof(uint64_t)); if (s != sizeof(uint64_t)){ printf("\n%s: eventfd read error. Exiting...",__func__); exit(EXIT_FAILURE); } printf("\n%s: Returned from read(), value read = %lld",__func__, eftd_ctr); } else if (retval == 0) { printf("\n%s: select() says that no data was available even after 10 seconds...",__func__); printf("\n%s: but lets try reading efd count anyway...",__func__); s = read(efd, &eftd_ctr, sizeof(uint64_t)); if (s != sizeof(uint64_t)){ printf("\n%s: eventfd read error. Exiting...",__func__); exit(EXIT_FAILURE); } printf("\n%s: Returned from read(), value read = %lld",__func__, eftd_ctr); exit(EXIT_FAILURE); } printf("\n%s: thread exiting...",__func__); pthread_exit(0); } int main() { pthread_t writing_thread_var, reading_thread_var; //Create eventfd efd = eventfd(0,0); if (efd == -1){ printf("\n%s: Unable to create eventfd! Exiting...",__func__); exit(EXIT_FAILURE); } printf("\n%s: eventfd created. value = %d. Spawning threads...",__func__,efd); //Create threads pthread_create(&writing_thread_var, NULL, writing_thread_func, NULL); pthread_create(&reading_thread_var, NULL, reading_thread_func, NULL); //Wait for threads to terminate pthread_join(writing_thread_var, NULL); pthread_join(reading_thread_var, NULL); printf("\n%s: closing eventfd. Exiting...",__func__); close(efd); exit(EXIT_SUCCESS); } 

所以这是一个愚蠢的错误:

我变了:

 retval = select(1, &rfds, NULL, NULL, &tv); 

至:

 retval = select(efd+1, &rfds, NULL, NULL, &tv); 

它的工作。

再次感谢@史蒂夫o