如何获取Stream的底层文件句柄?
我有一个使用物理内存快照(例如,VMware VMEM 文件)的应用程序。除此之外,它可以通过虚拟地址而不是物理地址从快照中读取进程/模块。这涉及通过页表一次重建 4KB 的模块,这又意味着对 Stream 的 Seek() 方法的大量调用。
由于我不确定的原因,这些对 Seek() 的调用使事情急剧恶化。因此,我正在寻找一种绕过它们的方法——或者至少是一种绕过托管 Seek() 实现的方法。我最好的猜测是 PInvoke SetFilePointer 并直接使用它,但为了做到这一点,我需要获取流的 IntPtr/SafeFileHandle 。我有一些限制:
我正在使用的 API 仅限于 .NET 3.5,因此不幸的是 MemoryMappedFile 不是一个选项。
我无法使用 FileStream(它已经有一个可以通过反射访问的私有 SafeFileHandle 字段)或 PInvoke CreateFile() 来以另一种方式获取快照 - 该 API 包含一个具有独占锁的 BinaryReader
当然,与 FileStream 不同,BinaryReader 及其底层 Stream 都没有对文件句柄的引用。但肯定存在一个吗?在这种情况下,我该如何获取它?
I have an application that works with physical memory snapshots (for example, VMware VMEM files). Among other things, it can read processes/modules out of the snapshot by virtual rather than physical address. This involves reconstructing the module 4KB at a time through the page table, which, in turn, means a lot of calls to the Stream's Seek() method.
For reasons I'm not sure of, these calls to Seek() bog things down dramatically. As a result, I'm looking for a way around them -- or at least, a way around the managed Seek() implementation. My best guess is to PInvoke SetFilePointer and work with that directly, but in order to do that I need to get the IntPtr/SafeFileHandle for the Stream. I have a few restrictions:
The API I'm working with is limited to .NET 3.5, so unfortunately MemoryMappedFile isn't an option.
I can't use a FileStream (which already has a private SafeFileHandle field that can be accessed with reflection) or PInvoke CreateFile() to get at the snapshot another way -- the API includes a BinaryReader that has an exclusive lock on the snapshot.
Of course, unlike FileStream, neither BinaryReader nor its underlying Stream have a reference to the file handle. But certainly one must exist? In which case, how do I go about acquiring it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Stream
没有文件句柄,因为它是一个抽象类。实现 Stream 的类可能会也可能不会使用文件句柄——FileStream
会使用文件句柄,因为它从文件中读取数据,但MemoryStream
会从文件中读取数据。例如,没有。要获取
BinaryReader
的底层文件句柄(在本例中为SafeFileHandle
),其Stream
是FileStream
,使用反射来访问private SafeFileHandle _handle
,如下所示:旁注:直接调用
SetFilePointer()
和MemoryMappedFile
都对此没有帮助 案件。似乎没有快速的方法来处理我正在使用的卷的随机磁盘访问(数百万个连续调用)。There's no file handle for
Stream
because it's an abstract class. A class implementingStream
may or may not use a file handle --FileStream
does, since it reads data from a file, butMemoryStream
, for example, does not.To get the underlying file handle (in this case a
SafeFileHandle
) of aBinaryReader
whoseStream
is aFileStream
, use reflection to accessprivate SafeFileHandle _handle
, like so:On a side note: neither direct calls to
SetFilePointer()
norMemoryMappedFile
helped in this case. It seems there's no fast way to handle random disk access at the volume I'm using it (millions of consecutive calls).由于您在
FileStream
上有BinaryReader
,因此您可以访问阅读器的BaseStream
,将其转换为FileStream
,然后使用其公共SafeFileHandle
属性来访问句柄。像这样的东西:Since you have
BinaryReader
overFileStream
you can access theBaseStream
of the reader, cast that toFileStream
and then use its publicSafeFileHandle
property to access the handle. Something like this: