многопоточность `select` не возвращает данные готово - PullRequest
0 голосов
/ 18 декабря 2018

Пример программы на C, запущенной в последней версии Linux:

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

Test

Введите строку текста после того, как увидите 3 ready (1 из основного потока и 2 из другогонитей).

Результат

От вызова select может быть 0, 1 или 2 потока и вывести ok.

Вопросы

  1. Почему не все заблокированные select звонки получают уведомление, когда данные становятся доступными?

  2. Почему read не уведомляет все select звонки, заблокированныена том же fd?

  3. Если данные станут доступны и поток не будет использоваться, будут ли все заблокированные вызовы select в конечном итоге уведомлены?

  4. Какиеиз приведенных выше ответов будет меняться, если вместо select?


будет использоваться *1036* Заменить 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 или нет).

...