背景
我正在开发一个C++ Windows应用程序。
我的应用程序将打开一些进程。 每个进程都会加载一个Logger DLL ,它提供了一个接口来注册日志事件,并决定何时以及如何将日志刷新到文件。
问题
假设我在Logger DLL定义了一个简单的决定:每次有100个日志事件被注册,将它们刷新到一个文件中。
尝试从用户模式进程创build全局文件映射对象失败
当两个进程尝试访问信号量为0的关键部分时会发生什么?
写共享内存的频率限制?
PHP中的共享内存文件
用户可能无法在Linux系统上打开共享内存对象的原因
如何确保只有一个DLL的实例执行刷新一次?
什么是最好的实践方法的情况下,跨进程共享一个DLL和它的一个行动只需要跨进程一次执行?
笔记
我们定义一个共享内存是至关重要的。 每个进程都需要知道其他进程的日志事件。 所以,我们不能让每个DLL实例都存储自己的日志并分别刷新它们。
如何使用内存映射文件在同一台计算机上的服务器和客户端之间进行通信?
共享内存中的Shared_dirty vs Private_dirty
Linux映射虚拟内存范围到现有的虚拟内存范围?
madvise(___,___,MADV_DONTNEED)是否指示操作系统懒惰地写入磁盘?
删除Linux上的所有共享内存和信号量
你的问题并没有说明日志架构是什么,例如,是附加到文件的事件,还是每次写入新文件? 当你写文件的事件,他们是从共享内存中删除?
在大多数情况下,你已经在跟踪(不管是哪种方式)哪些事件已经被写入,哪些事件还需要写入,所以决定是否有一百个待处理的事件是微不足道的。 您只需将此信息放入共享内存块中,并使用适当的同步障碍访问它。
但是,为了解决您提出的问题:
假设我在Logger DLL中定义了一个简单的决定:每次有100个日志事件被注册,将它们刷新到一个文件中。
你可以用一个简单的计数器来做到这一点,当然在共享内存。 如果由于某种原因,你不能把它放在现有的共享内存块中,你可以创建一个单独的内存块。
如果你已经被一个互斥锁保护了,这就像下面这样简单:
void count_new_event() { if ((*counter)++ == 100) { flush_events(); (*counter) = 0; } }
如果你想避免声明互斥量,你可以做这样的事情:
void count_new_event() { for (;;) { DWORD count = InterlockedCompareExchange(counter,99); if (count == 99) { // The count was 99,so this is the 100th call // The call to InterlockedCompareExchange reset the counter flush_events(); break; } else { if (InterlockedCompareExchange(counter,count + 1,count) == count) { // We've successfully incremented the counter break; } else { // Oops,someone got in before us; try again continue; } } } }
请注意,我没有测试过这个代码,也不一定是最有效的方法。 但是它应该在大多数情况下工作,并且如果你还没有拥有它,它会比声明互斥锁更有效率。
请注意,我假设flush_events将处理来自不同进程的调用重叠的场景。 这可能像声称互斥体一样简单。 如果不是这样,例如,如果一次刷新一百个事件可能效率不足以跟上新事件的发生率,那么几乎可以肯定跟踪哪些事件需要被写入。
如果你想定期刷新日志,你可以做一些类似的事情,比如每分钟一次,而不是每一百个事件。 只要记录共享内存中最后一次刷新的时间戳,并将其与当前时间进行比较。 如果您不想声明互斥锁,则可以使用InterlockedCompareExchange更新时间戳; 对InterlockedCompareExchange的调用将在一个进程中成功,所以这就是执行flush的那个。
我的建议是建立如下的东西:
一个日志管理器被引入(它可以是一个专用的独立进程)。 他的角色是:
提供一个监听套接字
时间管理
注册/取消注册客户端
管理哪个实例可以将日志刷新到日志文件。
每个DLL实例:
有自己的日志缓冲区
连接到管理器的套接字(自己注册)
从管理器接收命令以刷新缓冲区。
在触发器接收时,将自己的数据附加到日志文件并通知管理器工作完成。
而不是套接字,你也可以使用共享内存(或其他API)。 我发现个人插座更方便。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。