4

stdin を介してユーザー (またはサードパーティ) アプリケーション入力を処理するための別のスレッドを持つ Windows アプリケーションを開発しています。

WaitForMultipleObjectsこのスレッドは、次の 2 つのイベントで待機するように設計されています。

  1. 死の合図。このシグナルが発生すると、インターフェース処理スレッドがシャットダウンします。
  2. インターフェイス信号。この信号が発生すると、読み取り可能な入力が存在します。入力が読み取られ、処理されます。

Windows では、このスレッドは、Waitこれら 2 つのイベントのメイン ループに入ります (bWaitAllFALSE)。stdin ハンドルを待機すると、読み取りの準備ができた入力があり、他のイベントがアプリケーションの別の場所から設定されたときに信号を送る効果があります。

これは私が望むとおりに機能します。ビジーウェイトに入らずにイベントが発生するのを待ち、両方のイベントを同時に待ちます。

この機能を Linux に移植したいと考えていますが、目的の結果を得る方法がわかりません。基本的に、私が本当に欲しいのはこれです:

Linux では、stdin でのユーザー入力に即座に応答するようにスレッドを設計するにはどうすればよいですか? また、アプリケーションの他の場所から発生した kill フラグにも即座に応答できますか?

後者を達成するために、ユーザーがテキストを入力するまでブロックするcin、、、またはその他の機能を使用できないように思えます。それでも、コンソールベースのアプリケーションでブロックせずにユーザー入力を読み取る方法がわかりません。getsgetch

私は、アプリケーションの他の場所から終了できる別のスレッドでユーザー入力を処理することを含む、アーキテクチャの変更を受け入れます (これを行うためのより Linux 的な方法がある場合)。GCC 4.4 と Boost 1.51 を使用しています。

4

2 に答える 2

3

Linux でこれを行う標準的な方法は、select(2)システム コールを使用することです。ただし、ファイル記述子のみを待機でき、他の種類のオブジェクト (イベントなど) を待機できないという点で、selectは よりも制限されています。WaitForMultipleObjectsしたがって、これを回避する一般的な方法は、パイプを作成し、パイプにダミー値を「シグナル」として書き込むことです。

このようなもの:

// Error checking omitted for expository purposes
int pipefd[2];
pipe(pipefd);  // Create the pipe

while(1)
{
    // Create file descriptor set of stdin and the read end of the pipe
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds);
    FD_SET(pipefd[0], &fds);
    int maxfd = MAX(STDIN_FILENO, pipefd[0]);

    // Wait until input becomes available on either stdin or the pipe
    int num_available = select(&fds, NULL, NULL, NULL);

    // Read & process stdin if possible (will not block)
    if (FD_ISSET(STDIN_FILENO, &fds))
    {
        int n = read(STDIN_FILENO, buffer, size);
        ...
    }

    // Read & process pipe if possible (will not block)
    if (FD_ISSET(pipefd[0], &fds))
    {
        char dummy;
        read(pipefd[0], &dummy, 1);
        // Handle signal (e.g. break out of loop)
    }
}

次に、完了したことをスレッドに通知するには、パイプの書き込み側に 1 バイトを書き込みます。

char dummy = 42;
write(pipefd[1], &dummy, 1);
于 2012-11-06T21:49:28.450 に答える
1

libevselect(およびいくつかの同様の化身) は、sを保留できることを含め、便利な抽象化を提供しますsignal

「 An interface signal 」の発信元を変更するオプションがある場合は、代わりに使用するように変更することを検討できますraise

于 2012-11-06T21:58:56.747 に答える