如果我select
从多个线程调用同一个打开的文件描述符会发生什么?
这是在某处记录的吗?
根据POSIX 2008select
规范,没有什么可以禁止两个线程同时调用select
。
可以合理地推断,如果两个线程都在监视重叠的文件描述符集,并且一些公共文件描述符变得可读或可写或诊断出错误,那么两个线程最终可能会报告公共文件描述符已准备好。这无法保证;有时间问题需要担心,它可能取决于线程的调度等。这也意味着其中一个线程可能最终无法在文件描述符上找到要读取的数据,而该文件描述符被告知包含要读取的数据,这正是因为另一个线程首先到达那里。任何给定的数据字节将仅由其中一个线程读取。
根据Linux手册页,select
是线程安全函数和取消点。
在Linux某些操作系统上,一个线程会成功进入select
,而其他线程会被阻塞(的主体select
是临界区)。无论描述符被返回给第一个线程,那么成功进入的第二个线程select
可能会立即使用相同的集合唤醒,因为select
它是一个级别触发的接口。
因此,您不能在Linux那些操作系统上select
同时选择多组文件描述符。
Linux 似乎支持完全可重入执行,用这个测试程序演示:
void * reader (void *arg) {
int *fds = (int *)arg;
struct timeval to = { 2, 0 };
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fds[0], &rfds);
select(fds[0]+1, &rfds, 0, 0, &to);
}
int main () {
int sp[2];
pthread_t t[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, sp);
pthread_create(&t[0], 0, reader, sp);
pthread_create(&t[1], 0, reader, sp);
pthread_join(t[0], 0);
pthread_join(t[1], 0);
return 0;
}
在Linux上计时这个程序(我的是2.6.43),程序在2秒后返回,表明两个线程select
同时进入。