Udostępnij przez


Korzystanie z buforowanego Wejścia/Wyjścia

Sterownik obsługujący interaktywne lub powolne urządzenie, lub taki, który zwykle przesyła stosunkowo małe ilości danych naraz, powinien używać metody transferu buforowanego I/O. Użycie buforowanych operacji we/wy w przypadku małych, interaktywnych transferów poprawia ogólne użycie pamięci fizycznej, ponieważ menedżer pamięci nie musi blokować pełnej strony fizycznej dla każdego transferu, podobnie jak w przypadku sterowników, które żądają bezpośredniego we/wy. Ogólnie rzecz biorąc, wideo, klawiatura, mysz, szeregowe i równoległe sterowniki żądają buforowanych operacji we/wy.

Menedżer wejścia/wyjścia określa, że operacja I/O używa buforowanego wejścia/wyjścia w następujący sposób:

Na poniższej ilustracji pokazano, jak menedżer we/wy konfiguruje żądanie IRP_MJ_READ dla operacji transferu, która używa buforowanych operacji we/wy.

diagram ilustrujący buforowane we/wy dla buforów użytkownika.

Na rysunku przedstawiono przegląd sposobu używania wskaźnika SystemBuffer w IRP do przesyłania danych dla żądania odczytu, gdy sterownik wykonuje operację OR na flagach obiektu urządzenia z DO_BUFFERED_IO.

  1. Pewien zakres wirtualnych adresów przestrzeni użytkownika reprezentuje bufor bieżącego wątku, a jego zawartość może być przechowywana w pewnym zakresie adresów fizycznych opartych na stronach (ciemne cieniowanie na poprzedniej ilustracji).

  2. Menedżer we/wy obsługuje żądanie odczytu bieżącego wątku, w ramach którego wątek przekazuje zakres adresów wirtualnych przestrzeni użytkownika reprezentujących bufor.

  3. Menedżer we/wy sprawdza bufor dostarczony przez użytkownika pod kątem dostępności i wywołuje ExAllocatePoolWithTag, aby utworzyć niestronicowany bufor przestrzeni systemowej (SystemBuffer) o rozmiarze odpowiadającym buforowi dostarczonemu przez użytkownika.

  4. Menedżer I/O zapewnia dostęp do nowo przydzielonego SystemBuffer w IRP, który wysyła do sterownika.

    Jeśli na rysunku pokazano żądanie zapisu, menedżer we/wy skopiuje dane z buforu użytkownika do buforu systemu przed wysłaniem IRP do sterownika.

  5. W przypadku żądania odczytu pokazanego na poprzedniej ilustracji sterownik odczytuje dane z urządzenia do buforu przestrzeni systemowej. Pamięć dla tego buforu jest niestronicowana, a sterownik może bezpiecznie uzyskać dostęp do buforu bez konieczności wcześniejszego zablokowania. Gdy żądanie odczytu zostało spełnione, sterownik wywołuje funkcję IoCompleteRequest w odniesieniu do IRP.

  6. Gdy oryginalny wątek jest ponownie aktywny, menedżer we/wy kopiuje dane odczytywane z bufora systemowego do bufora użytkownika. Wywołuje również funkcję ExFreePool , aby zwolnić bufor systemu.

Po utworzeniu buforu przestrzeni systemowej dla sterownika przez menedżera we/wy, wątek trybu użytkownika może zostać zamieniony, a jego pamięć fizyczna może zostać ponownie użyta przez inny wątek, prawdopodobnie przez wątek należący do innego procesu. Jednak zakres adresów wirtualnych przestrzeni systemowej podany w IRP pozostaje prawidłowy, dopóki sterownik nie wywoła IoCompleteRequest z IRP.

Sterowniki, które przesyłają duże ilości danych w danym momencie, w szczególności sterowniki, które wykonują transfery wielostronicowe, nie powinny próbować używać buforowanych operacji we/wy. W trakcie działania systemu pula niestronicowana może zostać rozdrobniona, co uniemożliwia menedżerowi we/wy przydzielenie dużych, ciągłych buforów przestrzeni systemowej do wysyłania w IRP dla takiego sterownika.

Zazwyczaj sterownik używa buforowanych operacji we/wy dla niektórych typów IRP, takich jak żądania IRP_MJ_DEVICE_CONTROL, nawet jeśli używa również bezpośrednich operacji we/wy. Sterowniki korzystające z bezpośrednich operacji we/wy zazwyczaj robią to tylko dla żądań IRP_MJ_READ i IRP_MJ_WRITE, a także dla ewentualnych żądań IRP_MJ_INTERNAL_DEVICE_CONTROL zdefiniowanych przez sterownik, które wymagają dużych transferów danych.

Każde żądanie IRP_MJ_DEVICE_CONTROL i IRP_MJ_INTERNAL_DEVICE_CONTROL zawiera kod sterowania wejścia/wyjścia. Jeśli kod kontrolny we/wy wskazuje, że IRP musi być obsługiwany z użyciem buforowanego we/wy, menedżer we/wy używa pojedynczego bufora systemowego do reprezentowania buforów wejściowych i wyjściowych aplikacji użytkownika. Sterownik obsługujący taki kod kontrolny we/wy musi odczytywać dane wejściowe (jeśli istnieją) z buforu, a następnie dostarczać dane wyjściowe (jeśli istnieją), zastępując dane wejściowe. Aby uzyskać więcej informacji, zobacz Definiowanie kodów kontrolnych I/O.