6

我有一个使用物理内存快照的应用程序(例如,VMware VMEM 文件)。除其他外,它可以通过虚拟地址而不是物理地址从快照中读取进程/模块。这涉及通过页表一次重建 4KB 的模块,这反过来意味着对 Stream 的 Seek() 方法的大量调用。

由于我不确定的原因,这些对 Seek() 的调用使事情急剧下降。因此,我正在寻找一种解决方法——或者至少是一种解决托管 Seek() 实现的方法。我最好的猜测是 PInvoke SetFilePointer 并直接使用它,但为了做到这一点,我需要为 Stream 获取 IntPtr/SafeFileHandle。我有一些限制:

  1. 我正在使用的 API 仅限于 .NET 3.5,所以不幸的是 MemoryMappedFile 不是一个选项。

  2. 我不能使用 FileStream(它已经有一个可以通过反射访问的私有 SafeFileHandle 字段)或 PInvoke CreateFile() 以另一种方式获取快照——API 包括一个对快照具有排他锁的 BinaryReader。

当然,与 FileStream 不同,BinaryReader 及其底层 Stream 都没有对文件句柄的引用。但肯定存在一个吗?在这种情况下,我该如何获取它?

4

2 回答 2

4

Stream因为它是一个抽象类,所以没有文件句柄。实现的类Stream可能使用文件句柄,也可能不使用文件句柄——FileStream这样做,因为它从文件中读取数据,但是MemoryStream,例如,不使用。

要获取 a which is a的底层文件句柄(在本例中为 a SafeFileHandle),请使用反射来访问,如下所示:BinaryReaderStreamFileStreamprivate SafeFileHandle _handle

SafeFileHandle sfh = (SafeFileHandle)typeof(FileStream).GetField("_handle", BindingFlags.NonPublic | BindingFlags.Instance).GetValue((FileStream)YOUR_BINARY_READER.BaseStream)

附带说明:在这种情况下,既没有直接调用SetFilePointer()也没有MemoryMappedFile帮助。似乎没有快速的方法来处理我正在使用的卷上的随机磁盘访问(数百万次连续调用)。

于 2012-01-01T01:24:15.990 回答
1

既然你已经完成BinaryReader了,FileStream你可以访问BaseStream阅读器的,将其转换为FileStream然后使用它的公共SafeFileHandle属性来访问句柄。像这样的东西:

FileStream stream = (FileStream)(reader.BaseStream);
//use stream.SafeFileHandle
于 2012-06-06T10:53:07.870 回答