【问题标题】:Memory page write detection on Windows & LinuxWindows 和 Linux 上的内存页面写入检测
【发布时间】:2011-12-05 08:40:59
【问题描述】:

我目前正在研究世代垃圾收集器。这意味着只有最近的对象被遍历,幸存的对象(=从已知的根可以到达)被提升到老一代。当对象指向相同或老一代的其他对象时,这可以正常工作。但是,当较旧的对象指向较新的对象时,并且由于仅遍历较新的对象,指向的对象将被错误地收集。为避免这种情况,此类对象在每个 GC 阶段都会被显式标记和遍历。

显然这样的“父”对象是可变的,因为通过构造不可变的对象总是指向现有的对象。所以要成为“父”,一个对象必须在提升后进行修改,使其指向一个较新的对象。

要知道老一代的哪些对象指向年轻一代,我正在寻找一种透明地监控内存变化的方法。为此,我使用内存保护和信号/异常处理。内存页面设置为只读,这会导致在写入时引发信号/异常,在这种情况下,我将内存保护设置回读写并将地址记录在某处以进行进一步处理,并返回负责的代码异常恢复正常。这样,当 GC 触发时,我就知道去哪里寻找潜在的父母进行遍历。

在 Linux 上,我结合使用 mprotect/SIGSEGV 信号处理。在 Windows 上,我打算使用 VirtualProtect,但没有发现 SIGSEGV 处理的等效项。所以我的问题:

  1. 您将如何在 Windows 上执行此操作?异常处理 API 似乎相当混乱。

  2. 有没有更好的方法来知道哪些内存区域被修改了,这样我就不必做所有这些记账了?

我的代码是用纯 C 编写的。目前我需要调用者代码来显式标记修改的对象,但这很繁琐且容易出错,所以我正在寻找一种透明的方式来完成它。

提前致谢,弗雷德

【问题讨论】:

  • 结构化异常处理。
  • 我没有足够的专家来判断它是否真的相关,但你可能想看看这篇关于 pitfalls 的一种尝试和捕获内存探测的博客文章。跨度>
  • SEH 不幸需要 1. 编译器支持和 2. 将 try 块包装在客户端代码周围,因此它不适合我的目的。然而,VEH 可以工作。
  • FWIW,高性能虚拟机通常会在生成机器代码(例如在 JIT 中)时挂钩指针写入,并发出代码,该代码也会将脏页提示写入特殊数组,因为使用虚拟机完成这项工作是很慢。

标签: c linux winapi garbage-collection memory-mapping


【解决方案1】:

GetWriteWatch 是理想的。 文档here

【讨论】:

  • 谢谢,这正是我正在寻找的功能。我知道这个功能,但一开始很快就放弃了,因为它需要 XP 并且不适用于 64 位 Itanium 上的 32 位应用程序。但由于替代品也需要 XP,我想我将不得不放弃对 Win2000 的支持。
猜你喜欢
  • 2015-09-11
  • 2011-03-22
  • 2012-05-28
  • 2014-11-27
  • 2015-11-04
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多