【问题标题】:Select() doesn't recognise changes through FD_SET while blockingSelect() 在阻塞时无法通过 FD_SET 识别更改
【发布时间】:2013-07-23 18:42:29
【问题描述】:

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

【问题讨论】:

  • 完成 - 如果无法理解或无法理解我在做什么,请告诉我。

标签: c multithreading select client


【解决方案1】:

是的,正如您所怀疑的,select() 不会检测到从另一个线程对文件描述符集所做的更改。毕竟,如果没有某种神奇的机制来异步检测对特定内存位置的写入,它就无法有效地做到这一点。

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

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

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

【讨论】:

【解决方案2】:

为了做这样的事情,select 需要使用“当前”fd 集进行内部轮询,这确实是 CPU 开销,您将无法控制轮询的周期。我认为这就是 select 的意义所在。

【讨论】:

    猜你喜欢
    • 2017-07-18
    • 2014-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 2011-06-09
    相关资源
    最近更新 更多