在最新的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
。
为什么在数据可用时没有全部阻止select
的呼叫通知?
为什么read
没有通知在同一fd上阻塞的所有select
呼叫?
如果数据可用并且没有线程消耗,最终将通知所有阻塞的select
调用吗?
如果使用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
)。