来自多个线程的同一个fd上的`select`

And*_*zos 3 c linux networking

如果我select从多个线程调用相同的打开文件描述符会发生什么?

这是在某处记录的吗?

Jon*_*ler 6

根据POSIX 2008select规范,没有任何东西可以禁止两个线程同时进行调用select.

可以合理地推断,如果两个线程都监视重叠的文件描述符集并且一些公共文件描述符变得可读或可写或者诊断出错误,则两个线程可能最终得到公共文件描述符准备好的报告.这不能保证; 有时间问题需要担心,它可能取决于线程的调度等.这也意味着其中一个线程可能最终没有找到数据来读取文件描述符,它被告知包含要读取的数据,正是因为另一个线程首先到达那里.任何给定的数据字节将只由其中一个线程读取.


jxh*_*jxh 5

根据Linux 手册页select是线程安全函数和取消点。

Linux某些操作系统上,一个线程会成功进入select,而其他线程会被阻塞(的主体select是临界区)。无论描述符返回到第一个线程,然后成功进入的第二个线程select可能会立即使用相同的集合唤醒,因为它select是一个级别触发的接口。

因此,您不能selectLinux这些操作系统上同时选择多组文件描述符。

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;
}
Run Code Online (Sandbox Code Playgroud)

在 Linux 上计时这个程序(我的是 2.6.43)时,程序在 2 秒后返回,表明两个线程select同时进入。