2011-12-27 2 views
5

У меня есть приложение, которое работает с моментальными снимками физической памяти (например, VMware VMEM-файлы). Помимо прочего, он может считывать процессы/модули из моментального снимка по виртуальному, а не по физическому адресу. Это включает в себя восстановление модуля 4KB за один раз через таблицу страниц, что, в свою очередь, означает лот вызовов метода Stream's Seek().Как получить основной дескриптор файла Stream?

По причинам, о которых я не уверен, эти призывы к искам() болота резко опускаются. В результате я ищу способ обойти их - или, по крайней мере, способ реализации управляемого Seek(). Мое лучшее предположение - PInvoke SetFilePointer и работать с этим напрямую, но для этого мне нужно получить IntPtr/SafeFileHandle для потока. У меня есть несколько ограничений:

  1. В API Я работаю с ограничен .NET 3.5, поэтому, к сожалению, не является отображение файла в память вариант.

  2. Я не могу использовать FileStream (у которого уже есть личное поле SafeFileHandle, к которому можно получить доступ с отражением) или PInvoke CreateFile(), чтобы получить снимок другим способом - API включает BinaryReader, который имеет эксклюзивный блокировка моментального снимка.

Конечно, в отличие от FileStream, ни BinaryReader, ни его базовый Stream не имеют ссылки на дескриптор файла. Но, конечно, нужно существовать? В каком случае, как мне его приобрести?

+1

Какой тип «потока»? Не все потоки имеют файлы. –

+2

MemoryMappedFile в .NET 4.0 - это всего лишь управляемая оболочка вокруг собственного API, вы можете реализовать ее без особых проблем в течение 3.5 (следовательно, я уже видел многие реализации там). Тем не менее, мне кажется, что вы в основном зацикливаетесь на использовании файловой системы (помимо некоторого интеллектуального кэширования). Файл с отображением карты на карту дает вам самые быстрые результаты в описанном вами сценарии (по сравнению с готовыми решениями). – Polity

+0

@John Saunders: Спасибо, ваш вопрос побудил меня взглянуть на класс «BinaryReader», после чего я понял, что мне просто нужно опустить свойство «BaseStream» в «FileStream», а затем использовать отражение для доступа к ' SafeFileHandle'. Я был бы рад выбрать это как правильный ответ, если вы хотите его написать. – Wayside

ответ

3

Нет дескриптора файла для Stream, потому что это абстрактный класс. Класс, реализующий Stream, может использовать или не использовать дескриптор файла - FileStream делает, поскольку он считывает данные из файла, но, например, 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 
Смежные вопросы