如何获取Stream的底层文件句柄?

发布于 2024-12-23 02:58:16 字数 610 浏览 2 评论 0原文

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

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

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

  2. 我无法使用 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:

  1. The API I'm working with is limited to .NET 3.5, so unfortunately MemoryMappedFile isn't an option.

  2. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

诗酒趁年少 2024-12-30 02:58:17

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

要获取 BinaryReader 的底层文件句柄(在本例中为 SafeFileHandle),其 StreamFileStream,使用反射来访问 private SafeFileHandle _handle,如下所示:

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

旁注:直接调用 SetFilePointer()MemoryMappedFile 都对此没有帮助 案件。似乎没有快速的方法来处理我正在使用的卷的随机磁盘访问(数百万个连续调用)。

There's no file handle for Stream because it's an abstract class. A class implementing Stream may or may not use a file handle -- FileStream does, since it reads data from a file, but MemoryStream, for example, does not.

To get the underlying file handle (in this case a SafeFileHandle) of a BinaryReader whose Stream is a FileStream, use reflection to access private SafeFileHandle _handle, like so:

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

On a side note: neither direct calls to SetFilePointer() nor MemoryMappedFile 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).

是你 2024-12-30 02:58:17

由于您在 FileStream 上有 BinaryReader,因此您可以访问阅读器的 BaseStream,将其转换为 FileStream,然后使用其公共 SafeFileHandle 属性来访问句柄。像这样的东西:

FileStream stream = (FileStream)(reader.BaseStream);
//use stream.SafeFileHandle

Since you have BinaryReader over FileStream you can access the BaseStream of the reader, cast that to FileStream and then use its public SafeFileHandle property to access the handle. Something like this:

FileStream stream = (FileStream)(reader.BaseStream);
//use stream.SafeFileHandle
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文