C ++で、別のプロセスからスレッドのロックを解除します
-
22-07-2019 - |
質問
プロセス間通信モジュール(プロセスAおよびプロセスB)をプログラミングしています。
プロセスAが特定のアクションを終了するとすぐに、Bの通信スレッドを実行(ロック解除)する方法はありますか?つまり、Bがポーリングを実行せず、Aがアクションを終了した後もBが待機しすぎるということですか?
これらの問題を支配する概念/モデル/設計パターンはどれですか? (プロセス間同期よりも正確なもの)。どのライブラリ/メソッドをお勧めしますか?
ありがとう。
編集:3つの主要OS(Ms Windows、Apple Mac OS X、GNU / Linux)のそれぞれに適した方法を探しています。
解決
これは非常に難しい仕事です:
Unix OSの場合:
-
pthread条件およびsetpshared引数を使用したミューテックス。
注:Linux 2.6、Solarisで十分にサポートされていますが、FreeBSDおよびCygwinはサポートしていません(Mac OS Xについては知りません)
-
Unixの場合、名前付きセマフォも使用できますが、それらのサポートレベルはわかりません
- Windowsにはいくつかのイベントがあります...
これは、特にIPCにとっては大変な仕事です...
したがって、ポータブルなものが必要な場合は、条件とミューテックスを持つBoost.Interprocessを確認することをお勧めします...
ただし、サポートするすべてのOSですべての機能がサポートされていることを確認してください。
Boost.Interprocessに関する注意事項
Boost.Interprosessは常にサポートされているわけではないpthread_ *関数を使用しているため、作業する必要がある各Unix OSのサポートのレベルを慎重に確認してください... p>
また、Windowsでこのような機能がどのように機能するかを確認してください(「共有メモリ内」がないことを知っている限り)。一般的に名前が付けられたオブジェクトを使用する必要があるため、Win32 APIのミューテックスを使用する必要があります。サポート対象と方法を確認してください。
他のヒント
編集: IPC用に改訂されたスレッド間同期が必要だと誤って考えた
待機可能なイベントのようなものが必要だと思います。
Windowsでは、 CreateEvent( )
、名前付きの自動リセットイベントを作成(または既存のものを取得)する。
プロセスAが処理を完了すると、 < code> SetEvent() 、プロセスBは WaitForSingleObject()
は、完了する(またはタイムアウトする)までスリープします。
別の方法として、 CreateSemaphore()
、0に初期化されます。
プロセスAは、 ReleaseSemaphore()<を呼び出して、完了を通知します。 / code>
、プロセスBは再びを使用します WaitForSingleObject()
が完了するまで待機します。
LinuxおよびOS Xでは、セマフォを使用して同様の効果を得ることができます。
sem_open()
を使用して、0を初期値とする名前付きセマフォを作成します。
プロセスAが完了すると、 sem_post()
はセマフォをインクリメントしますが、プロセスBは sem_wait()
が完了するまでスリープします。
注:セマフォメソッドは複数の完了を通知できる場合があります。Windowsで最大カウントを設定するか、 sem_getvalue()
条件変数はあなたがやろうとしているものに合うと思います。LinuxとOSXで動作するサンプルを次に示します
#include <pthread.h>
/* no error checking, quick and dirty sample */
pthread_mutex_t g_mutex;
pthread_cond_t g_cond;
int a_done = 0;
void init(void)
{
pthread_mutex_init(&g_mutex, NULL);
pthread_cond_init(&g_cond, NULL);
}
void thread_a(void *arg)
{
/* do something here... */
pthread_mutex_lock(&g_mutex);
a_done = 1;
pthread_cond_signal(&g_cond);
pthread_mutex_unlock(&g_mutex);
}
void thread_b(void *arg)
{
/* wait for a to complete */
pthread_mutex_lock(&g_mutex);
while (!a_done)
pthread_cond_wait(&g_cond, &g_mutex);
a_done = 0;
pthread_mutex_unlock(&g_mutex);
}
Windowsでは、 pthreads-win32 、またはVistaでのネイティブ条件変数を使用できます。詳細については、 MSDN条件変数ページをご覧ください。
参照:
OSがシグナルをサポートしている場合、シグナルハンドラーからミューテックスのロックを解除し、タスクが完了するとすぐにプロセスAからシグナルを送信できます。
プロセスBはミューテックスまたは他の同期ツールで待機し、Aは何でも動作します。その後、たとえば、完了時にシグナルUSR1を送信し、プロセスBのUSR1ハンドラーが対応する同期ツールをロック解除します。
最も一般的なのは、select()/ poll()を使用することです。利用可能な入力がある場合、両方ともいくつかのファイル記述子をチェックできます。両方ともタイムアウトパラメータを受け取ります-これにより、100%のCPUを消費する可能性のあるビジー待機を防ぎます。これは、小規模/中規模のアプリケーションに非常に適したソリューションです。
別のアプローチは、別のスレッドでポーリングを行うことです。
大きなアプリケーションを開発する場合は、 ACEに注目する価値があります。フレームワークまたは ブースト。これらのフレームワークは、クロスプラットフォームソリューションであり、適切に設計され、十分にテストされています。
まあ、私の意見と経験では、ポータブルで簡単な方法でそれを行う最良の方法はソケットを使用することです。さらに、必要に応じて、異なるマシンで2つのプロセスを使用することもできます。さらに、コミュニケーションを拡張して、同期以上のものを処理できます。
ポーリングを行いたくない場合は、ソケットで同期メッセージを待機するスレッドを使用します。ソケットをブロック方式で読み取ります。メッセージを受信すると、標準のマルチスレッド同期を使用して同期を処理します。 BはAが終了するまで待機する必要があるため、プロセスをブロックする方法で読み取る必要があります。