Select()在阻塞时无法识别通过FD_SET进行的更改

5
我正在调用FD_SET()来设置非阻塞套接字的write_fd,而select()在另一个线程中阻塞 - 问题是,即使fd准备好写入,select()仍然会阻塞。
实际上我想做的是:在另一个线程中准备要写入此套接字的数据,之后将套接字添加到write_fd中。select()线程应该能够识别并处理准备好的数据。
select()在阻塞时不会识别fd内的更改吗? 如果是这样的话,是否有类似于epoll() EPOLL_CTL_MOD而不是FD_SET()来更新集合的方法?或者唯一的方法是设置select()函数的超时时间以识别更改?
在我看来,那不是一个解决方案,因为那会很“慢”,并且会产生CPU开销...
编辑:
// This thread is running all day long ...
static void * workman() {
    FD_ZERO(&fd_read);
    FD_ZERO(&fd_write);
    FD_SET(socketId , &fd_read);

    while(1) {
        // PROBLEM Keeps blocking when box() is called
        select(socketId+1, &fd_read, &fd_write, NULL, NULL);

        if(FD_ISSET(socketId, &fd_read)) {
            // RECIVE DATA
        }
        else if(FD_ISSET(socketId, &fd_write)) {
            FD_CLR(socketId, &fd_write);
            pthread_mutex_lock(&interface.mutex);
                strncpy(conn.outBuffer, interface.buffer, strlen(interface.buffer));
                interface.buffer[0] = '\0';
            pthread_mutex_unlock(&interface.mutex);
            // SEND DATA
        }
    }

    return 0;
}

// This function is called within another thread on user input
int box(char *content) {
    pthread_mutex_lock(&interface.mutex);
        // preparing the data and write it into interface.buffer if available
    pthread_mutex_unlock(&interface.mutex);

    FD_SET(socketId, &fd_write);

    return 0;
}

完成 - 如果不可理解或者不足以理解我在做什么,请告诉我。 - Genius
2个回答

5
是的,正如您所猜测的那样,select()无法检测到其他线程对文件描述符集所做的更改。毕竟,它不能有效地做到这一点,没有一些神奇的机制来异步检测特定内存位置的写操作。
是的,您应该使用epoll接口。 epoll_wait的手册明确指出了其他线程的更改是如何处理的。

当一个线程被阻塞在调用 epoll_pwait() 时,另一个线程可以将文件描述符添加到等待的 epoll 实例中。如果新文件描述符变为就绪,它将导致 epoll_wait() 调用取消阻塞。

但是,如果您无法使用支持此类更改的epoll或另一个文件通知接口,则仍然有解决方案。您可以使用内部的pipe(或类似的机制,例如eventfd),在更新文件描述符集后导致select返回并重新启动。当然,您应该小心进行适当的锁定以避免竞争条件。 同样,请务必将管道设置为非阻塞模式,否则在高负载下,针对管道写端的write可能会被阻塞,可能会导致程序死锁。

谢谢...我很愿意这样做,但问题是epoll不可用:http://stackoverflow.com/questions/12327275/is-epoll-epoll-wait-etc-available-for-ios - Genius
至少一个解决方案。 谢谢! - Genius

1
为了做类似这样的事情,选择会需要内部轮询“当前”fd集合,这实际上会增加CPU负担,并且您将无法控制轮询的周期。我想这就是select的作用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接