[英]Creating global named counter shared between processes
如何在c ++中創建可以在多個進程之間共享的全局計數器值? 我需要的是一種使多個進程立即“無效”的方法,以信號通知它們執行某些操作(例如從文件讀取)。 所有進程都將連續輪詢(每10ms)以獲取當前計數器值,並將其與內部存儲的最后一個值進行比較。 值不匹配將表明需要做一些工作。
編輯:順便說一句,我的進程正在執行為不同的.exe:s,而不是從某些父進程創建的。 操作系統是Windows。
命名信號量呢? Posix支持它,不確定Windows。
考慮一下您要分配信息的方式和潛在的重疊-如果任何讀者完成閱讀所花的時間比刷新所花費的時間長,那么您將在建議的方法中遇到麻煩。
我閱讀問題的方式有很多讀者,作者不知道(或在大多數情況下)一次有多少讀者,但想通知讀者有新內容可供閱讀。
如果不知道有多少潛在的讀者,就無法使用簡單的互斥或信號量來了解何時完成閱讀器,不知道每個人何時完成,就無法掌握何時重置事件以通知下一個事件的好信息。讀取事件。
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-雙重事件
假設任何一個讀周期都比寫事件之間的時間短得多。 創建2個手動重置事件,在任何時候最多會發信號通知其中一個事件,並在事件之間交替。 信令將立即釋放所有閱讀器,完成閱讀后,他們將等待替代事件。
您可以使用簡便的方法,也可以使用簡便的方法將共享值存儲在注冊表或文件中,以便所有進程都同意經常檢查它。
困難的方法是使用IPC(進程間通信,我最常用的方法是NamedPipes。它不太難,因為您可以在網上找到很多有關IPC的資源。
如果使用* nix,則可以使進程從命名管道 (或套接字)中讀取,然后在其中寫入特定的msg,以告知其他進程應關閉它們。
使用具有手動重置功能的命名事件對象。 以下解決方案使用CPU不如忙等待
發送過程:
接收流程:
Sleep(10)實際上可能比Sleep(20)花費更長的時間,但這只會導致另一個周期(再次讀取未更改的文件)。
由於可執行文件的名稱是已知的,所以幾天前我在一個項目中用C#實現了另一個解決方案:每個讀取器進程都創建一個命名事件“ Global \\ someuniquestring_%u”,其中%u是它的進程ID。 。 如果發出事件信號,則讀取文件並進行工作。 發送者進程具有事件句柄列表,如果文件已更改,則將它們設置為活動狀態,從而通知所有讀取器進程。 有時,例如,當文件已更改時,它必須更新事件句柄列表:
找到了一種監視文件夾更改(使用“ event_trigger” -event)並從文件讀取其他事件信息的解決方案:
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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.