[英]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.