首页 文章

使用eventfd,Select()无法正常运行

提问于
浏览
2

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

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

知道为什么会这样吗?在我看来,select()不能正常工作 .

PS:这个问题与linux - Can't get eventfd to work with epoll together类似

还有其他人面临类似问题吗?

#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);
}

1 回答

  • 1

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

    我变了:

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

    至:

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

    它工作 .

    再次感谢@ Steve-o

相关问题