如何创建可在c ++中的多个进程之间共享的全局计数器值?我需要的是一种“一次”使多个进程“无效”的方法,指示它们执行某些操作(比如从文件读取)。所有进程将连续轮询(每10ms)获取当前计数器值,并将其与内部存储的最后一个值进行比较。不匹配的值表明需要做一些工作。
编辑:顺便说一下,我的进程是以不同的.exe:s执行的,不是从某个父进程创建的。操作系统是windows。
答案 0 :(得分:2)
命名信号量怎么样? Posix支持它,不确定窗口。
答案 1 :(得分: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 :(得分:0)
你可以通过简单的方式或方式来做到这一点 简单的方法是在注册表或文件中存储共享值,以便所有进程同意经常检查它。
困难的方法是使用IPC(进程间通信,我使用的最常用的方法是NamedPipes。它不太难,因为你可以在网上找到大量关于IPC的资源。
答案 3 :(得分:0)
如果您使用* nix,则可以从named pipe(或套接字)读取进程,然后在那里写入特定的msg以告知其他进程应该关闭。
答案 4 :(得分:0)
使用指定的事件对象手动重置。以下解决方案不会使用CPU,而是忙于等待
发送过程:
接收流程:
睡眠(10)实际上可能需要比睡眠(20)更长的时间,但这只会导致另一个循环(再次读取未更改的文件)。
答案 5 :(得分:0)
由于已知可执行文件的名称,我在几天前在项目中实现了另一种解决方案(在C#中): 每个读者进程都创建一个命名事件“Global \ someuniquestring_%u”,其中%u是它的进程ID。如果发出事件信号,请阅读文件并完成工作。 发件人进程有一个事件句柄列表,如果文件已更改,则将它们设置为活动状态,从而通知所有读取器进程。有时,例如当文件发生变化时,它必须更新事件句柄列表:
答案 6 :(得分:0)
找到一个监控文件夹更改的解决方案(使用“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;
}