4

WaitForMultipleObjects() と同様の機能が必要な Linux プラットフォーム用のマルチスレッド C++ プログラムを実装しています。

解決策を探しているときに、Linux で WaitForMultipleObjects() 機能を実現する方法を例を挙げて説明している記事があることに気付きましたが、それらの例は私がサポートしなければならないシナリオを満たしていません。

私の場合のシナリオは非常に単純です。メインスレッドがメソッド/コールバックをDLLなどの外界に公開するデーモンプロセスがあります。DLL のコードは私の管理下にありません。同じメインスレッドが新しいスレッド「スレッド 1」を作成します。スレッド 1 は、シャットダウン イベント (デーモン シャットダウン) を待機する無限ループのようなものを実行する必要があります。または、上記の公開されたメソッド/コールバックを通じて通知されるデータ利用可能イベントを待機します。

要するに、スレッドはシャットダウンイベントとデータ利用可能イベントで待機します。シャットダウンイベントが通知された場合、待機が満たされ、ループが中断されるか、データ利用可能イベントが通知された場合、待機も満たされ、スレッドがビジネス処理を実行します。

Windowsでは、非常に簡単に見えます。以下は、私のシナリオの MS Windows ベースの疑似コードです。

//**Main thread**

//Load the DLL
LoadLibrary("some DLL")

//Create a new thread
hThread1 = __beginthreadex(..., &ThreadProc, ...)

//callback in main thread (mentioned in above description) which would be called by the     DLL
void Callbackfunc(data)
{
    qdata.push(data);
    SetEvent(s_hDataAvailableEvent);
}

void OnShutdown()
{
    SetEvent(g_hShutdownEvent);
    WaitforSingleObject(hThread1,..., INFINITE);
    //Cleanup here
}

//**Thread 1**

unsigned int WINAPI ThreadProc(void *pObject)
{
    while (true)
    {

        HANDLE hEvents[2];
        hEvents[0] = g_hShutdownEvent;
        hEvents[1] = s_hDataAvailableEvent;

        //3rd parameter is set to FALSE that means the wait should satisfy if state of  any one of the objects is signaled.
        dwEvent = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
        switch (dwEvent) 
        {   
            case WAIT_OBJECT_0 + 0: 
            // Shutdown event is set, break the loop
            return 0;   

            case WAIT_OBJECT_0 + 1:
            //do business processing here
            break; 

            default: 
            // error handling
        }
    }
}

Linuxにも同じことを実装したい。Linuxに関しては、私の理解によると、シグナルを登録する必要があるメカニズムがまったく異なります。終了シグナルが到着すると、プロセスはシャットダウンしようとしていることを認識しますが、その前に、プロセスは実行中のスレッドが正常にシャットダウンするのを待つ必要があります。

4

2 に答える 2

1

Unix または Linux 固有のコードを書きたい場合は、さまざまな API を利用できます。

  • pthread: スレッド、ミューテックス、条件変数を提供します
  • IPC (プロセス間通信) メカニズム: ミューテックス、セマフォ、共有メモリ
  • 信号

スレッドの場合、最初のライブラリは必須です (Linux には低レベルの syscall がありますが、より面倒です)。イベントの場合は、3 つを使用できます。

システム シャットダウン イベントは、関連するすべてのプロセスにブロードキャストされる終了 (SIG_TERM) および強制終了 (SIG_KILL) シグナルを生成します。したがって、個々のデーモンのシャットダウンもこの方法で開始できます。ゲームの目的は、シグナルをキャッチし、プロセスのシャットダウンを開始することです。重要な点は次のとおりです。

  • シグナルメカニズムは、それらを待つ必要がないように作られています

    を使用していわゆるハンドラをインストールするだけsigactionで、残りはシステムが行います。

  • シグナルはプロセスに設定され、任意のスレッドがそれをインターセプトできます (ハンドラーは任意のコンテキストで実行できます)。

    したがって、シグナル ハンドラーをインストールし ( sigaction(2)を参照)、アプリケーションが終了する必要がある他のスレッドに何らかの方法で情報を渡す必要があります。

おそらく最も便利な方法は、すべてのスレッドが定期的に参照するグローバルミューテックス保護フラグを設定することです。シグナル ハンドラは、そのフラグを設定してシャットダウンを示します。ワーカー スレッドの場合は、

  • サーバーが閉じていることをリモートホストに伝え、
  • 読み取り時にソケットを閉じる
  • 残りのすべての受信コマンド/データを処理し、応答を送信する
  • ソケットを閉じる
  • 出口

メイン スレッドの場合、これはワーカー スレッドで結合を開始してから終了することを意味します。

このモデルは、データが通常処理される方法に干渉するべきではありません: へのブロッキング呼び出しは、selectまたはシグナルが捕捉された場合pollにエラーを返しますEINTR。非ブロッキング呼び出しの場合、スレッドは定期的にフラグをチェックするため、機能します。

于 2013-04-16T14:56:38.440 に答える