Udostępnij za pośrednictwem


Uzyskiwanie dostępu do buforów danych w sterownikach WDF (KMDF lub UMDF)

Gdy sterownik Windows Driver Frameworks (WDF) odbiera żądanie odczytu, zapisu lub sterowania urządzeniem we/wy, obiekt żądania zawiera bufor wejściowy, bufor wyjściowy lub oba.

Bufory wejściowe zawierają informacje wymagane przez sterownik. W przypadku żądań zapisu te informacje są zwykle danymi, które sterownik funkcji musi wysyłać do urządzenia. W przypadku żądań sterowania we/wy urządzenia bufor wejściowy może zawierać informacje wskazujące typ operacji, którą musi wykonać sterownik.

wyjściowe bufory przyjmują informacje ze sterownika. W przypadku żądań odczytu te informacje są zwykle danymi odbieranym przez sterownik funkcji z urządzenia. W przypadku żądań sterowania we/wy urządzenia bufor wyjściowy może odbierać stan lub inne informacje określone przez kod kontrolny we/wy żądania.

Technika, jakiej używa sterownik do uzyskiwania dostępu do buforów danych żądania, zależy od metody uzyskiwania dostępu do buforów danych przez sterownik dla urządzenia. Istnieją trzy metody dostępu:

  • buforowane wejścia/wyjścia. Menedżer we/wy tworzy pośrednie bufory, które współdzieli ze sterownikiem.
  • Direct I/O. Menedżer we/wy blokuje przestrzeń buforową w pamięci fizycznej, a następnie zapewnia sterownikowi bezpośredni dostęp do tej przestrzeni.
  • Ani buforowane, ani bezpośrednie I/O. Menedżer we/wy udostępnia sterownikowi wirtualne adresy przestrzeni buforowej żądania. Menedżer we/wy nie weryfikuje przestrzeni buforowej żądania, dlatego sterownik musi sprawdzić, czy przestrzeń buforowa jest dostępna i zablokować ją w pamięci fizycznej.

Sterownik Kernel-Mode Driver Framework (KMDF) może używać dowolnej z trzech metod dostępu. Sterownik User-Mode Driver Framework (UMDF) może używać buforowanego lub bezpośredniego we/wy na potrzeby żądań odczytu, zapisu i IOCTL oraz może przekonwertować żądania określające metodę METHOD_NEITHER.

określanie metody dostępu buforu

sterowników KMDF

W przypadku żądań odczytu i zapisu wszystkie sterowniki w stosie sterowników muszą używać tej samej metody dostępu do buforów urządzenia, z wyjątkiem sterownika najwyższego poziomu, który może używać metody "żadna", niezależnie od tego, której metody używają niższe sterowniki.

Począwszy od wersji 1.13, sterownik KMDF określa metodę dostępu dla wszystkich żądań odczytu i zapisu urządzenia przez wywołanie WdfDeviceInitSetIoTypeEx dla każdego urządzenia. Jeśli na przykład sterownik określa buforowaną metodę we/wy dla jednego z jego urządzeń, menedżer we/wy używa buforowanej metody we/wy podczas dostarczania żądań odczytu i zapisu do sterownika dla tego urządzenia.

W przypadku żądań kontroli wejścia/wyjścia urządzenia kod kontrolny we/wy (IOCTL) zawiera bity określające metodę dostępu do buforu. W związku z tym sterownik KMDF nie musi podejmować żadnych działań, aby wybrać metodę buforowania dla IOCTLs. Aby uzyskać więcej informacji na temat IOCTLs, zobacz Definiowanie kodów kontrolek we/wy. W przeciwieństwie do żądań odczytu i zapisu, wszystkie IOCTLs urządzenia nie muszą określać tej samej metody dostępu.

sterowniki UMDF

Sterownik UMDF określa preferencji dla metody dostępu używanej przez platformę na potrzeby żądań odczytu i zapisu, a także żądań kontroli we/wy urządzenia. Wartości, które udostępnia sterownik UMDF, są tylko preferencjami i nie mają gwarancji, że są używane przez strukturę. Aby uzyskać więcej informacji, zobacz Zarządzanie metodami dostępu buforu w sterownikach UMDF.

Sterownik UMDF określa metodę dostępu dla wszystkich żądań odczytu, zapisu i IOCTL urządzenia przez wywołanie WdfDeviceInitSetIoTypeEx dla każdego urządzenia. Jeśli na przykład sterownik określa buforowaną metodę we/wy dla jednego z jego urządzeń, platforma używa buforowanej metody we/wy podczas dostarczania żądań odczytu, zapisu i IOCTL do sterownika dla tego urządzenia.

Zwróć uwagę na różnicę w metodzie dostępu do buforu dla IOCTL między frameworkami KMDF a UMDF. Sterowniki KMDF nie specyfikują metody dostępu buforu dla IOCTL, natomiast sterowniki UMDF specyfikują metodę dostępu buforu dla IOCTL.

Jeśli sterownik WDF opisuje bufor żądania we/wy przy użyciu techniki nieprawidłowej dla metody we/wy używanej przez obiekt docelowy we/wy, struktura poprawia opis buforu. Jeśli na przykład sterownik używa MDL do opisania bufora, który przekazuje do WdfIoTargetSendReadSynchronously, a docelowy obiekt I/O używa buforowanego I/O (które wymaga określenia buforów przy użyciu adresów wirtualnych zamiast MDL), wówczas framework konwertuje opis bufora z MDL na adres wirtualny i długość. Jest to jednak bardziej wydajne, jeśli w poprawnym formacie sterownik określa bufory.

Aby uzyskać informacje o obiektach pamięci struktury, listach odkładających, MDL i lokalnych buforach, zobacz Using Memory Buffers.

Aby uzyskać informacje na temat usuwania pamięci, zobacz cykl życia buforu pamięci.

uzyskiwanie dostępu do buforów dla buforowanych operacji we/wy

Jeśli sterownik używa buforowanego we/wy, jego zachowanie zmienia się w zależności od typu żądania danych oraz tego, czy używa KMDF, czy UMDF.

KMDF sterowniki

Gdy sterownik KMDF używa buforowanego we/wy, menedżer we/wy tworzy jeden bufor pośredni, do którego sterownik może uzyskać dostęp dla każdego typu żądania. Oto, co się stanie:

  • Pisanie próśb. Menedżer we/wy przesyła informacje wejściowe z buforu wejściowego aplikacji wywołującej przed wywołaniem stosu sterowników. Następnie sterownik KMDF odczytuje informacje wejściowe z buforu pośredniego i zapisuje je na urządzeniu.
  • Odczytywanie żądań. Sterownik KMDF odczytuje informacje z urządzenia i przechowuje je w buforze pośrednim. Następnie menedżer we/wy kopiuje dane wyjściowe z buforu pośredniego do buforu wyjściowego aplikacji.
  • Żądania kontroli we/wy urządzenia. Sterownik KMDF odczytuje lub zapisuje dane dla tego żądania do lub z buforu pośredniego.

Sterowników UMDF

Gdy sterownik UMDF używa buforowanego I/O, proces hostujący sterownik tworzy jeden lub dwa pośrednie bufory, w zależności od typu żądania. Oto, co się stanie:

  • Napisz żądania. Struktura tworzy jeden bufor, przesyła informacje wejściowe z buforu wejściowego aplikacji wywołującej, a następnie wywołuje stos sterowników. Sterownik UMDF odczytuje informacje wejściowe z buforu pośredniego i zapisuje je na urządzeniu.
  • Odczytaj żądania. Sterownik UMDF odczytuje informacje z urządzenia i przechowuje je w buforze utworzonym przez strukturę. Proces hosta sterownika kopiuje dane wyjściowe z buforu pośredniego do buforu wyjściowego aplikacji.
  • Żądania kontroli wejścia/wyjścia urządzeń. Framework tworzy dwa bufory odpowiadające buforom wejściowym i wyjściowym IOCTL, do których sterownik może uzyskać dostęp. Struktura kopiuje informacje wejściowe z IOCTL do nowego buforu pośredniego i udostępnia je sterownikowi. Struktura nie kopiuje zawartości buforu wyjściowego, więc sterownik nie powinien próbować go odczytać (w przeciwnym razie spowoduje odczytanie danych bezużytecznych). Wszystkie dane, które sterownik zapisuje w buforze wyjściowym, są kopiowane z powrotem do oryginalnego buforu IOCTL i są zwracane do aplikacji po pomyślnym zakończeniu żądania we/wy. Należy pamiętać, że wszystkie dane, które sterownik zapisuje w buforze wejściowym, są odrzucane i nie są zwracane do aplikacji wywołującej.

Aby pobrać dojście do obiektu pamięci platformy reprezentującego bufor, sterowniki KMDF i UMDF wywołają WdfRequestRetrieveInputMemory lub WdfRequestRetrieveOutputMemory, w zależności od tego, czy jest to żądanie odczytu, czy zapisu. Następnie sterownik może uzyskać wskaźnik do buforu, wywołując WdfMemoryGetBuffer. Aby odczytać i zapisać bufor, sterownik wywołuje WdfMemoryCopyFromBuffer lub WdfMemoryCopyToBuffer.

Aby pobrać adres wirtualny i długość buforu, sterownik wywołuje WdfRequestRetrieveInputBuffer lub WdfRequestRetrieveOutputBuffer.

Aby przydzielić i skompilować listę deskryptorów pamięci (MDL) dla buforu, sterownik KMDF wywołuje WdfRequestRetrieveInputWdmMdl lub WdfRequestRetrieveOutputWdmMdl.

Uzyskiwanie dostępu do buforów danych dla bezpośrednich operacji we/wy

Sterowniki KMDF

Jeśli sterownik korzysta z bezpośrednich operacji we/wy, menedżer operacji we/wy weryfikuje dostępność obszaru buforowego, który inicjator żądania operacji we/wy (zazwyczaj aplikacja trybu użytkownika) określił, blokuje ten obszar w pamięci fizycznej, a następnie zapewnia sterownikowi bezpośredni dostęp do tego obszaru buforowego.

sterowników UMDF

Jeśli sterownik określił preferencje dotyczące bezpośredniego we/wy, a wszystkie wymagania UMDF dotyczące bezpośredniego we/wy zostały spełnione (zobacz Zarządzanie metodami dostępu buforu w sterownikach UMDF), struktura mapuje bufor pamięci odbierany z menedżera we/wy bezpośrednio do przestrzeni adresowej procesu hosta sterownika, a tym samym zapewnia sterownikowi bezpośredni dostęp do przestrzeni buforu.

Aby pobrać dojście do obiektu pamięci struktury reprezentującego miejsce buforu, sterownik wywołuje WdfRequestRetrieveInputMemory lub WdfRequestRetrieveOutputMemory. Sterownik może następnie pobrać wskaźnik do buforu, wywołując WdfMemoryGetBuffer. Aby odczytać i zapisać bufor, sterownik wywołuje WdfMemoryCopyFromBuffer lub WdfMemoryCopyToBuffer.

Aby pobrać adres wirtualny i długość przestrzeni buforu, sterownik wywołuje WdfRequestRetrieveInputBuffer lub WdfRequestRetrieveOutputBuffer.

Jeśli sterowniki urządzenia używają bezpośrednich operacji we/wy, menedżer we/wy opisuje bufory przy użyciu list MDL. Aby pobrać wskaźnik do MDL buforu, sterownik KMDF wywołuje WdfRequestRetrieveInputWdmMdl lub WdfRequestRetrieveOutputWdmMdl. Sterownik UMDF nie może uzyskać dostępu do MDLs.

Uzyskiwanie dostępu do buforów danych dla operacji we/wy ani buforowanych, ani bezpośrednich

sterowników KMDF

Jeśli sterownik używa metody dostępu do buforu znanej jako ani jako buforowanego we/wy, ani jako metody bezpośredniego we/wy (lub krótko, metodą „ani”), menedżer we/wy po prostu dostarcza sterownikowi adresy wirtualne, które inicjator żądania we/wy określił dla przestrzeni buforowej żądania. Menedżer we/wy nie weryfikuje pamięci bufora dla żądania we/wy, więc sterownik musi sprawdzić, czy obszar bufora jest dostępny i zablokować go w pamięci fizycznej.

Adresy wirtualne, które dostarcza menedżer wejścia/wyjścia, mogą być dostępne tylko w kontekście danego procesu inicjującego żądanie wejścia/wyjścia. Tylko sterownik najwyższego poziomu w stosie sterowników ma gwarancję wykonania w kontekście procesu inicjatora.

Aby uzyskać dostęp do miejsca buforowego żądania we/wy, sterownik najwyższego poziomu musi dostarczyć funkcję wywołania zwrotnego EvtIoInCallerContext. Struktura wywołuje tę funkcję wywołania zwrotnego za każdym razem, gdy odbiera żądanie we/wy dla sterownika.

Jeśli metoda dostępu buforu żądania jest "żadna z dwóch", sterownik KMDF musi wykonać następujące czynności dla każdego buforu:

  1. Wywołaj WdfRequestRetrieveUnsafeUserInputBuffer lub WdfRequestRetrieveUnsafeUserOutputBuffer w celu uzyskania adresu wirtualnego buforu.

  2. Wywołaj WdfRequestProbeAndLockUserBufferForRead lub WdfRequestProbeAndLockUserBufferForWrite, aby zbadać i zablokować bufor oraz uzyskać uchwyt do obiektu pamięci frameworku dla tego bufora.

  3. Zapisz uchwyty obiektu pamięci w przestrzeni kontekstowej żądania.

  4. Wywołaj funkcję WdfDeviceEnqueueRequest, który zwraca żądanie do platformy.

Struktura następnie dodaje żądanie do jednej z kolejek I/O sterownika. Jeśli sterownik dostarczył procedur obsługi żądań, struktura ostatecznie wywoła odpowiednią procedurę obsługi żądań.

Procedura obsługi żądań może pobrać dojścia obiektu pamięci żądania z przestrzeni kontekstowej żądania. Sterownik może przekazać uchwyty do WdfMemoryGetBuffer w celu uzyskania adresu bufora.

Czasami sterownik najwyższego poziomu musi użyć powyższych kroków, aby uzyskać dostęp do buforu trybu użytkownika, nawet jeśli sterownik nie korzysta z metody dostępu "ani". Załóżmy na przykład, że sterownik używa buforowanego we/wy. Kod kontrolny we/wy, który używa buforowanej metody dostępu, może przekazać strukturę zawierającą osadzony wskaźnik do buforu trybu użytkownika. W takim przypadku sterownik musi podać funkcję wywołania zwrotnego EvtIoInCallerContext, która wyodrębnia wskaźniki ze struktury, a następnie używa poprzednich kroków od 2 do 4.

sterowników UMDF

UMDF nie obsługuje ani buforów buforowanych, ani bezpośrednich typu we/wy, więc sterownik UMDF nigdy nie musi obsługiwać tego typu buforów bezpośrednio.

Jednakże, jeśli framework odbiera takie bufory do odczytu lub zapisu od menedżera we/wy, udostępnia je sterownikowi UMDF jako buforowane we/wy lub bezpośrednie we/wy, w zależności od metody dostępu wybranej przez sterownik. Jeśli platforma odbiera IOCTL określającą metodę buforu "żadna", opcjonalnie może przekonwertować metodę dostępu buforu żądania IOCTL na buforowane we/wy lub bezpośrednie we/wy na podstawie obecności dyrektywy INF. Aby uzyskać więcej informacji, zobacz Zarządzanie metodami dostępu buforu w sterownikach UMDF.