Как получить основной дескриптор файла потока? - PullRequest
6 голосов
/ 27 декабря 2011

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

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

  1. API, с которым я работаю, ограничен .NET 3.5, поэтому, к сожалению, MemoryMappedFile не подходит.

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

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

Ответы [ 2 ]

4 голосов
/ 01 января 2012

Нет дескриптора файла для 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 голос
/ 06 июня 2012

Поскольку у вас есть BinaryReader сверх FileStream, вы можете получить доступ к BaseStream считывателя, привести его к FileStream и затем использовать его открытое свойство SafeFileHandle для доступа к дескриптору.Как то так:

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