阻止时,Select()无法通过FD_SET识别更改

时间:2013-07-23 18:42:30

标签: c multithreading select client

我正在调用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;
}

2 个答案:

答案 0 :(得分:4)

是的,正如您所怀疑的那样,select()将不会检测到来自另一个线程的文件描述符集所做的更改。毕竟,如果没有一些神奇的机制可以异步检测到特定内存位置的写入,它就无法有效地完成。

而且,是的,您应该使用epoll界面。 epoll_wait的手册页特别指出,处理来自另一个线程的更改。

  

虽然在调用epoll_pwait()时阻塞了一个线程,但确实如此   可能为另一个线程添加文件描述符   等待epoll实例。如果新文件描述符准备就绪,   它会导致epoll_wait()调用解除阻塞。

但是,如果您无法使用支持此类更改的epoll或其他文件通知界面,则仍有解决方案。您可以使用内部pipe(或eventfd之类的类似机制),在更新文件描述符集后使select返回并重新启动。当然,你应该小心做正确的锁定,以避免竞争条件。同样,请务必将管道置于非阻塞模式,否则管道写入端的write可能会在高负载下阻塞,并可能导致程序死锁。

答案 1 :(得分:0)

为了做类似的事情,选择需要使用" current"进行内部轮询。 fd set,这实际上是一个CPU开销,你将无法控制轮询的周期。这就是我认为的选择。