【发布时间】:2011-12-27 02:27:18
【问题描述】:
我有一个使用物理内存快照(例如,VMware VMEM 文件)的应用程序。除其他外,它可以通过虚拟地址而不是物理地址从快照中读取进程/模块。这涉及通过页表一次重建 4KB 的模块,这反过来意味着对 Stream 的 Seek() 方法的大量调用。
由于我不确定的原因,这些对 Seek() 的调用使事情急剧下降。因此,我正在寻找一种解决方法——或者至少是一种解决托管 Seek() 实现的方法。我最好的猜测是 PInvoke SetFilePointer 并直接使用它,但为了做到这一点,我需要为 Stream 获取 IntPtr/SafeFileHandle。我有一些限制:
我使用的 API 仅限于 .NET 3.5,所以很遗憾 MemoryMappedFile 不是一个选项。
我不能使用 FileStream(它已经有一个可以通过反射访问的私有 SafeFileHandle 字段)或 PInvoke CreateFile() 以另一种方式获取快照——API 包括一个具有快照的排他锁。
当然,与 FileStream 不同,BinaryReader 及其底层 Stream 都没有对文件句柄的引用。但肯定存在一个吗?在这种情况下,我该如何获取它?
【问题讨论】:
-
什么样的
Stream?并非所有流都有文件句柄。 -
.NET 4.0 中的 MemoryMappedFile 只是原生 API 的托管包装器,您应该能够在 3.5 中轻松实现它(因此,我已经看到了很多实现)。就是说,在我看来,您主要是坚持使用文件系统(除了一些智能缓存)。到目前为止,内存映射文件可以在您描述的场景中为您提供最快的结果(与开箱即用的解决方案相比)。
-
@John Saunders:谢谢,您的问题促使我再次查看
BinaryReader类,然后我意识到我只需要将BaseStream属性向下转换为FileStream,然后使用反射访问SafeFileHandle。如果您想写出来,我很乐意选择它作为正确答案。 -
@Polity:感谢您提供 MemoryMappedFile 提示。我一定会调查的。