2011-12-27 68 views
5

我有一個適用於物理內存快照的應用程序(例如,VMware VMEM文件)。除此之外,它可以通過虛擬而不是物理地址從快照中讀取進程/模塊。這涉及通過頁表一次重建模塊4KB,這又意味着對Stream的Seek()方法的調用的。如何獲取Stream的基礎文件句柄?

由於我不確定的原因,這些調用Seek()使事情急劇下降。因此,我正在尋找一種解決方法 - 或者至少是一種圍繞管理的Seek()實現的方法。我最好的猜測是PInvoke SetFilePointer並直接使用,但爲了做到這一點,我需要爲Stream獲取IntPtr/SafeFileHandle。我有一些限制:

  1. 我正在使用的API僅限於.NET 3.5,所以不幸的是MemoryMappedFile不是一個選項。

  2. 我不能使用FileStream(已經有一個可以通過反射訪問的私有SafeFileHandle字段)或PInvoke CreateFile()以另一種方式獲取快照 - API包括一個BinaryReader,鎖定快照。

當然,與FileStream不同,BinaryReader及其底層Stream都沒有引用文件句柄。但是肯定存在?在這種情況下,我該如何去獲取它?

+1

什麼樣的'Stream'?並非所有的流都有文件句柄。 – 2011-12-27 02:35:40

+2

.NET 4.0中的MemoryMappedFile只是本地API的管理包裝器,您應該能夠在3.5內實現它而不會有太多麻煩(因此,我已經看到很多實現已經存在)。這就是說,聽起來你大部分都停留在使用文件系統(除了一些智能緩存)之外。內存映射文件到目前爲止在您描述的場景中爲您提供了最快的結果(與開箱即用的解決方案相比)。 – Polity 2011-12-27 03:04:02

+0

@John Saunders:謝謝,您的問題促使我再次查看'BinaryReader'類,於是我意識到我只需將'BaseStream'屬性向下翻轉爲'FileStream',然後使用反射來訪問' SafeFileHandle'。如果你想寫出來,我很樂意選擇這個答案作爲正確的答案。 – Wayside 2011-12-27 03:23:55

回答

3

Stream沒有文件句柄,因爲它是一個抽象類。實施Stream的類可能會或可能不會使用文件句柄,因爲它從文件讀取數據,但是例如MemoryStream不會。

爲了獲得基本的文件句柄(在這種情況下SafeFileHandle)一BinaryReader,其Stream的是FileStream,使用反射來訪問private SafeFileHandle _handle,就像這樣:

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

在一個側面說明:既不直接調用到SetFilePointer()MemoryMappedFile幫助在這種情況下。似乎沒有快速的方法來處理我使用它的卷(連續數百萬次調用)的隨機磁盤訪問。

1

既然你有BinaryReader超過FileStream您可以訪問閱讀器的BaseStream,強制轉換成FileStream,然後使用它的公共SafeFileHandle屬性來訪問手柄。類似這樣的:

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