多线程“选择”未返回准备就绪的数据

时间:2018-12-18 16:29:30

标签: linux select linux-kernel posix

在最新的Linux版本上运行的示例C程序:

#include <pthread.h>
#include <sys/select.h>
#include <unistd.h>

void *func(void *arg) {
    fd_set rfds;
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    write(1, "ready\n", 6);
    select(1, &rfds, 0, 0, 0);
    write(1, "ok\n", 3);
}

int main() {
    pthread_t t[2];
    pthread_create(&t[0], 0, func, 0);
    pthread_create(&t[1], 0, func, 0);
    write(1, "ready\n", 6);
    char buf[1024];
    read(0, buf, 1024);
    pthread_join(t[0], 0);
    pthread_join(t[1], 0);
    return 0;
}

测试

在看到3 ready(主线程中的1和其他线程中的2)之后键入一行文本。

结果

select调用可能返回0、1或2个线程并打印ok

问题

  1. 为什么在数据可用时没有全部阻止select的呼叫通知?

  2. 为什么read没有通知在同一fd上阻塞的所有select呼叫?

  3. 如果数据可用并且没有线程消耗,最终将通知所有阻塞的select调用吗?

  4. 如果使用epoll而不是select,以上答案中的哪些会改变?


select替换为epoll

#include <pthread.h>
#include <stdio.h>
#include <sys/epoll.h>
#include <unistd.h>

void *func(void *arg) {
    int epollfd = epoll_create1(0);
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = 0;
    epoll_ctl(epollfd, EPOLL_CTL_ADD, 0, &ev);
    struct epoll_event events[1];
    write(1, "ready\n", 6);
    int nfds = epoll_wait(epollfd, events, 1, -1);
    write(1, "ok\n", 3);
}

int main() {
    pthread_t t[2];
    pthread_create(&t[0], 0, func, 0);
    pthread_create(&t[1], 0, func, 0);
    write(1, "ready\n", 6);
    char buf[1024];
    read(0, buf, 1024);
    pthread_join(t[0], 0);
    pthread_join(t[1], 0);
    return 0;
}

但是它给出了相同的结果:可能有0、1或2个线程从epoll_wait返回并打印ok(是否为EPOLLET)。

0 个答案:

没有答案