我有一个适用于物理内存快照的应用程序(例如,VMware VMEM文件)。除此之外,它还可以通过虚拟而非物理地址从快照中读取进程/模块。这涉及通过页表一次重建4KB模块,这反过来意味着对Stream的Seek()方法的 lot 调用。
由于我不确定的原因,这些对Seek()的调用使事情陷入困境。因此,我正在寻找一种解决方法 - 或者至少是围绕托管Seek()实现的方法。我最好的猜测是PInvoke SetFilePointer并直接使用它,但为了做到这一点,我需要为Stream获取IntPtr / SafeFileHandle。我有一些限制:
我正在使用的API仅限于.NET 3.5,所以不幸的是MemoryMappedFile不是一个选项。
我不能使用FileStream(已经有可以通过反射访问的私有SafeFileHandle字段)或PInvoke CreateFile()以另一种方式获取快照 - 该API包含一个BinaryReader,它具有对快照的独占锁定。
当然,与FileStream不同,BinaryReader及其底层Stream都没有对文件句柄的引用。但肯定必须存在一个?在这种情况下,我该如何获取它?
答案 0 :(得分:4)
Stream
没有文件句柄,因为它是一个抽象类。实现Stream
的类可能会也可能不会使用文件句柄 - FileStream
,因为它从文件中读取数据,但是MemoryStream
例如不会。
要获取其SafeFileHandle
为BinaryReader
的{{1}}的基础文件句柄(在本例中为Stream
),请使用反射来访问FileStream
,像这样:
private SafeFileHandle _handle
旁注:在这种情况下,直接拨打SafeFileHandle sfh = (SafeFileHandle)typeof(FileStream).GetField("_handle", BindingFlags.NonPublic | BindingFlags.Instance).GetValue((FileStream)YOUR_BINARY_READER.BaseStream)
和SetFilePointer()
都没有帮助。似乎没有快速的方法来处理使用它的卷(数百万个连续呼叫)的随机磁盘访问。
答案 1 :(得分:1)
由于BinaryReader
超过FileStream
,您可以访问阅读器的BaseStream
,将其转换为FileStream
,然后使用其公共SafeFileHandle
属性进入手柄。像这样:
FileStream stream = (FileStream)(reader.BaseStream);
//use stream.SafeFileHandle