如果我在多个线程的同一个打开文件描述符上调用select
会怎样?
这是在某处记录的吗?
答案 0 :(得分:6)
根据POSIX 2008 select
规范,没有任何内容禁止两个线程同时调用select
。
可以合理地推断,如果两个线程都监视重叠的文件描述符集并且某些公共文件描述符变得可读或可写或者诊断出错误,则两个线程最终都会得到一个报告,即公共文件描述符是准备。这不能保证;有时间问题需要担心,它可能取决于线程的调度等。这也意味着其中一个线程可能最终没有找到数据来读取文件描述符,它被告知包含要读取的数据,正是因为另一个线程首先到达那里。只有一个线程会读取任何给定的数据字节。
答案 1 :(得分:3)
根据Linux manual page,select
是线程安全函数和取消点。
在 Linux 某些操作系统上,一个线程将成功进入select
,而其他线程将被阻塞(select
的主体是一个关键部分)。无论返回到第一个线程的描述符是什么,然后成功输入select
的第二个线程可能会立即使用相同的集合唤醒,因为select
是一个级别触发的接口。
因此,您无法使用select
在 Linux 这些操作系统上同时选择多组文件描述符。
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
。