Пример программы на 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
.
Вопросы
Почему не все заблокированные select
звонки получают уведомление, когда данные становятся доступными?
Почему read
не уведомляет все select
звонки, заблокированныена том же fd?
Если данные станут доступны и поток не будет использоваться, будут ли все заблокированные вызовы select
в конечном итоге уведомлены?
Какиеиз приведенных выше ответов будет меняться, если вместо 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
или нет).