2010-11-23 11 views
1

C++で複数のプロセス間で共有できるグローバルカウンタ値を作成するにはどうすればよいですか?私が必要とするのは、複数のプロセスを一度に「無効にする」方法です(ファイルからの読み込みなど)。すべてのプロセスは、現在のカウンタ値を連続的にポーリングし(10msごとに)、内部的に格納された最後の値と比較します。不一致の値は、いくつかの作業が必要であることを示します。プロセス間で共有されるグローバル名前付きカウンタの作成

編集: btw私のプロセスは別の.exe:sという名前で実行されていますが、いくつかの親プロセスからは作成されていません。オペレーティングシステムはウィンドウです。

+0

Windowsや* nixの? – karlphillip

+0

なぜイベントオブジェクトを使用しないのですか? – wj32

+0

@ wj32:mutexと似ていますか?一度に1つのプロセスのみを通知します。 – AareP

答えて

0

簡単な方法または方法 共有の値をレジストリまたはファイルに保存して、すべてのプロセスが頻繁にチェックすることに同意することが簡単な方法です。

ハードな方法は、IPC(プロセス間通信、私はNamedPipesのある使用の最も一般的な方法を使用することです。そのない難しすぎるあなたがネット上でIPCに関するリソースの多くを見つけることができますので。

+0

ええ、IPCに関する情報を見つけるのは簡単ですが、難しいことを理解しています。 :) – AareP

0

あなたがいる場合* nixの上であなたはnamed pipe(またはソケット)から読み取るプロセスを作成し、その彼らがシャットダウンすべき他のプロセスを伝えるためにそこに特定のMSGを書くことができます。

IPC performance: Named Pipe vs Socket

Windows NAmed Pipes alternative in Linux

+0

実際に私はそれらのパイプがどのように機能するのだろうと思っていました。パイプの受信側に複数のリーダーがあるとどうなりますか?メッセージはFIFO順に配信されますか? – AareP

+0

複数の読者の場合は、代わりにソケットを使用する必要があります:http://stackoverflow.com/questions/1634580/named-pipes-fifos-on-unix-with-multiple-readers – karlphillip

1

情報と潜在的なオーバーラップを配布する方法を検討してください。読者が読書を完了するのに時間がかかり、リフレッシュに時間がかかる場合は、提案された方法で問題に陥るでしょう。

あなたの質問を読んだやり方は、複数の読者がいますが、ライターは一度に読者の数を知っていません(または大部分は気にしませんが)。読む。

シンプルなミューテックスやセマフォーを使用して読者がいつ完了したかを知ることができない場合、潜在的な読者数が分からず、いつイベントをリセットするかについての良い情報がない次の読み取りイベントを通知します。

MS、Windowsの特定:
一つのオプションは、共有データセグメント内の変数を配置することです

共有セグメント。これは、同じ変数を同じセグメントに名前を付けたすべてのexeによって読み込み(および書き込む)ことができることを意味します。つまり、共有DLLをロードしたDLLに入れた場合です。

詳細はhttp://www.codeproject.com/KB/DLL/data_seg_share.aspxを参照してください。

// Note: Be very wary of using anything other than primitive types here! 
#pragma data_seg(".mysegmentname") 
HWND hWnd = NULL; 
LONG nVersion = -1; 
#pragma data_seg() 
#pragma comment(linker, "/section:.mysegmentname,rws") 

IPC - COM
各イベントシンクへの変更を押し出す、労働者がイベントのために登録することができ、あなたのメインアプリCOMサービスを行います。

IPC - 任意の1点のリードサイクルを想定すると、デュアルイベントは
書き込みイベント間の時間よりもはるかに少ないです。 2つの手動リセットイベントを作成します。これらのイベントのうち最大1つはいつでも通知され、イベントが交互に表示されます。シグナリングは即座にすべての読者を解放し、完了したら代替イベントを待つ。

2

名前付きセマフォーはどうですか? Posixはそれをサポートしていますが、ウィンドウについてはわかりません。

+0

Windowsもそうです。 –

+0

セマフォを使用すると、WaitForSingleObject()呼び出しによって各プロセスのセマフォの値が減少し、一度に実行されるプロセスの量は任意です。 – AareP

0

名前付きイベントオブジェクトを手動リセットとともに使用します。次のソリューションは、待って忙しいよりもそんなにCPUを使用していません

送信プロセス:

  • セットイベント
  • スリープ10ミリ秒
  • リセットイベント

受信プロセス:

  • すべての待機中のプロセスイベントが設定されたときにパスする
  • ファイルを読み取る
  • 20msの間スリープさせて、同じイベントを2回見ることはできません。
  • は、実際にスリープ(20)が、(再び変更しないファイルを読み込む)別のサイクルで、この結果だけよりも時間がかかることがあります再び

スリープ(10)待ちます。

+0

実際、私のプロセスはイベントを待っているだけではありません。彼らはまた忙しい他のものがあります。だから私は彼らがイベントの状態を確認するために10msか1000msかかるかどうかは言えません。 – AareP

0

実行可能ファイルの名前がわかっているので、わずか数日前のプロジェクトで(C#で)実装した別の解決方法があります。 すべてのリーダープロセスは、名前付きイベント "Global \ someuniquestring_%u"あなたはプロセスIDです。イベントが通知された場合は、ファイルを読み込んで作業を行います。 送信者プロセスにはイベントハンドルのリストがあり、ファイルが変更された場合はアクティブに設定され、すべての読み取りプロセスが通知されます。時折、ファイルが変更されたとき、それはイベントのリストを更新する必要がありますハンドル:

  • は、すべてのプロセスの名前を持つすべてのプロセスのreader.exe '(例えば)
  • はそれがハンドルID
  • 開きますゲット新しいプロセスの場合、既存のイベント "Global \ someuniquestring_%u"に対して
  • 実行中のプロセスのハンドルをすべて閉じます。ファイルから読み込むと、追加イベント情報( "event_trigger" -event付き)監視フォルダの変更のための
0

見つかり一つの解決策:

HANDLE event_trigger; 
__int64 event_last_time; 
vector<string> event_info_args; 
string event_info_file = "event_info.ini"; 

// On init 
event_trigger = FindFirstChangeNotification(".", false, FILE_NOTIFY_CHANGE_LAST_WRITE); 
event_last_time = stat_mtime_force("event_info.ini"); 

// On tick 
if (WaitForSingleObject(event_trigger, 0)==0) 
{ 
    ResetEventTrigger(event_trigger); 

    if (stat_mtime_changed("event_info.ini", event_last_time)) 
    { 
     FILE* file = fopen_force("event_info.ini"); 

     char buf[4096]; 
     assert(fgets(buf, sizeof(buf), file)); 
     split(buf, event_info_args, "\t\r\n"); 
     fclose(file); 

     // Process event_info_args here... 

     HWND wnd = ...; 
     InvalidateRect(wnd,0,false); 
    } 
} 

// On event invokation 
FILE* file = fopen("event_info.ini", "wt"); 
assert(file); 
fprintf(file,"%s\t%s\t%d\n", 
    "par1", "par2", 1234); 
fclose(file); 

stat_mtime_changed("event_info.ini", event_last_time); 


// Helper functions: 
void ResetEventTrigger() 
{ 
    do 
    { 
     FindNextChangeNotification(evt); 
    } 
    while(WaitForSingleObject(evt, 0)==0); 
} 
FILE* fopen_force(const char* file); 
{ 
    FILE* f = fopen(file, "rt"); 
    while(!f) 
    { 
     Sleep(10+(rand()%100)); 
     f = fopen(f, "rt"); 
    } 
    assert(f); 
    return f; 
} 
__int64 stat_mtime_force(const char* file) 
{ 
    struct stat stats; 
    int res = stat(file, &stats); 
    if(res!=0) 
    { 
     FILE* f = fopen(file, "wt"); 
     fclose(f); 
     res = stat(file, &stats); 
    } 
    assert(res==0); 
    return stats.st_mtime; 
} 
bool stat_mtime_changed(const char* file, __int64& time); 
{ 
    __int64 newTime = stat_mtime(file); 
    if (newTime - time > 0) 
    { 
     time = newTime; 
     return true; 
    } 
    return false; 
} 
関連する問題