5

select() が別のスレッド内でブロックしている間に、非ブロック ソケットの write_fd を設定するために FD_SET() を呼び出しています。

私が実際にやりたいことは、別のスレッド内でこのソケットに書き込むデータを準備し、その後ソケットを write_fd に追加することです。select() スレッドはそれを認識し、準備されたデータを処理する必要があります。

ブロック中に select() は fd 内の変更を認識しませんか? はいの場合 – セットを更新するための FD_SET() の代わりに epoll() EPOLL_CTL_MOD のようなものがあります。または、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;
}
4

2 に答える 2

5

はい、ご想像のとおり、select()別のスレッドからファイル記述子セットに加えられた変更を検出しません。結局のところ、特定のメモリ位置への書き込みを非同期的に検出する魔法のメカニズムがなければ、効率的にそれを行うことはできません。

そして、はい、epollインターフェイスを使用する必要があります。の man ページにはepoll_wait、別のスレッドからの変更が処理されることが特に記載されています。

epoll_pwait() の呼び出しで 1 つのスレッドがブロックされている間に、別のスレッドが待機中の epoll インスタンスにファイル記述子を追加する可能性があります。新しいファイル記述子の準備が整うと、epoll_wait() 呼び出しのブロックが解除されます。

epollただし、そのような変更をサポートする別のファイル通知インターフェイスを使用できない場合でも、解決策があります。内部pipe(または などの同様のメカニズムeventfd) を使用しselectて、ファイル記述子セットを更新した後に復帰して再起動することができます。もちろん、競合状態を避けるために適切なロックを行うように注意する必要があります。同様に、必ずパイプをノンブロッキング モードにしてください。そうしないとwrite、パイプの書き込み側が高負荷下でブロックされ、プログラムがデッドロックする可能性があります。

于 2013-07-23T19:29:39.117 に答える