2011-12-27 17 views
5

Mam aplikację współpracującą z migawkami pamięci fizycznej (na przykład pliki VMware VMware). Między innymi może odczytywać procesy/moduły z migawki przez wirtualny, a nie fizyczny adres. Obejmuje to rekonstrukcję modułu 4KB w czasie za pośrednictwem tabeli stron, co z kolei oznacza lot wywołań do metody Stream's Seek().Jak uzyskać podstawowy uchwyt pliku strumienia?

Z powodów, których nie jestem pewien, te wywołania funkcji Seek() powodują drastyczne obniżenie wartości. W rezultacie szukam sposobu obejścia ich - lub przynajmniej sposobu obejścia zarządzanej implementacji Seek(). Domyślam się, że należy PInvoke SetFilePointer i pracować z tym bezpośrednio, ale aby to zrobić, potrzebuję uzyskać IntPtr/SafeFileHandle dla strumienia. Mam kilka ograniczeń:

  1. Interfejs API, z którym pracuję, jest ograniczony do .NET 3.5, więc niestety MemoryMappedFile nie jest opcją.

  2. nie mogę użyć FileStream (który ma już prywatną pole SafeFileHandle którego można uzyskać dostęp z odbicia) lub pinvoke CreateFile(), aby dostać się na migawce inny sposób - API zawiera BinaryReader że ma wyłączne zablokuj migawkę.

Oczywiście, w przeciwieństwie do FileStream, ani BinaryReader ani jego bazowy Stream mają odniesienie do uchwytu pliku. Ale na pewno trzeba istnieć? W takim razie, jak mam go zdobyć?

+1

Co to jest 'Stream'? Nie wszystkie strumienie mają uchwyty plików. –

+2

MemoryMappedFile w .NET 4.0 jest właśnie zarządzanym opakowaniem wokół natywnego API, powinieneś być w stanie zaimplementować go bez większych problemów w obrębie 3.5 (stąd, widziałem już wiele implementacji tam). To powiedziawszy, wydaje mi się, że najczęściej utknąłeś w używaniu systemu plików (oprócz inteligentnego buforowania). Plik odwzorowany w pamięci zdecydowanie daje najszybsze wyniki możliwe w opisanym scenariuszu (w porównaniu do gotowych rozwiązań dostarczanych). – Polity

+0

@John Saunders: Dziękuję, twoje pytanie skłoniło mnie do ponownego przyjrzenia się klasie 'BinaryReader', po czym zdałem sobie sprawę, że po prostu potrzebuję downcast 'BaseStream' do' FileStream', a następnie użyj refleksji, aby uzyskać dostęp do '' SafeFileHandle'. Byłbym szczęśliwy, wybierając tę ​​poprawną odpowiedź, jeśli chcesz ją zapisać. – Wayside

Odpowiedz

3

Nie ma uchwytu pliku dla Stream, ponieważ jest to klasa abstrakcyjna. Klasa implementująca Stream może, ale nie musi, używać uchwytu pliku - FileStream, ponieważ odczytuje dane z pliku, ale na przykład tego nie robi.

Aby uzyskać podstawową uchwyt pliku (w tym przypadku SafeFileHandle) z BinaryReader którego Stream jest FileStream, użycie odbicie, aby uzyskać dostęp private SafeFileHandle _handle, tak:

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

Na marginesie: ani połączenia bezpośrednie do SetFilePointer() ani MemoryMappedFile pomógł w tym przypadku. Wygląda na to, że nie ma szybkiego sposobu radzenia sobie z przypadkowym dostępem do dysku przy woluminie, z którego go używam (miliony kolejnych połączeń).

1

Skoro masz BinaryReader nad FileStream można uzyskać dostęp do BaseStream czytelnika, że ​​aby rzucić FileStream a następnie użyć jej własność publiczną SafeFileHandle dostęp do uchwytu. Coś takiego:

FileStream stream = (FileStream)(reader.BaseStream); 
//use stream.SafeFileHandle 
Powiązane problemy