Dela via


Använda direkt I/O med PIO

En drivrutin som använder programmerad I/O (PIO) i stället för DMA måste dubbelt mappa användarutrymmesbuffertar till ett systemutrymmesadressintervall. Följande bild visar hur I/O-chefen konfigurerar en IRP_MJ_READ begäran om en PIO-överföringsåtgärd som använder direkt I/O.

diagram som illustrerar direkt i/o för enheter som använder pio.

Bilden visar hur en enhet som använder PIO hanterar samma uppgift.

  1. Ett visst intervall av virtuella adresser för användarutrymme representerar den aktuella trådens buffert, och buffertens innehåll kan faktiskt lagras på några fysiskt icke-sammanhängande sidor. Om buffertlängden inte är noll skapar I/O-chefen en MDL för att beskriva bufferten.

  2. I/O-chefen servar den aktuella trådens läsbegäran, för vilken tråden skickar ett intervall med virtuella adresser för användarutrymme som representerar en buffert.

  3. I/O-hanteraren eller FSD:n kontrollerar den användartillhandahållna bufferten för åtkomlighet. Om I/O-chefen har skapat en MDL anropas MmProbeAndLockPages med en MDL, vilket anger intervallet för virtuella adresser för användarbufferten. MmProbeAndLockPages fyller även i motsvarande fysiska adressintervall i MDL.

  4. I/O-chefen ger en pekare till MDL (MdlAddress) i en IRP som begär en överföringsåtgärd. Tills I/O-hanteraren eller filsystemet anropar MmUnlockPages när drivrutinen har slutfört IRP förblir de fysiska sidorna som beskrivs i MDL låsta och tilldelade till bufferten. De virtuella adresserna i en sådan MDL kan dock bli osynliga (och ogiltiga), även innan IRP skickas till enhetsdrivrutinen eller till någon mellanliggande drivrutin som kan vara skiktad ovanför enhetsdrivrutinen.

  5. Om drivrutinen kräver virtuella systemadresser, anropar den MmGetSystemAddressForMdlSafe med IRP:s MdlAddress pekare för att dubbla mappa användarutrymmets virtuella adresser i MDL till ett adressintervall i systemutrymmet. I bilden ovan representerar AliasBuff den MDL som beskriver de dubbelt mappade adresserna.

  6. Drivrutinen använder det virtuella adressintervallet för systemutrymmet från den dubbelt mappade MDL (AliasBuff) för att läsa in data i minnet.

När drivrutinen slutför IRP genom att anropa IoCompleteRequest, frigör I/O-hanteraren eller filsystemet MDL:ens dubbelt mappade systemutrymmesområde om drivrutinen har anropat MmGetSystemAddressForMdlSafe. I/O-hanteraren eller filsystemet låser upp de sidor som beskrivs i MDL och tar bort MDL och IRP för drivrutinens räkning. För bättre prestanda bör drivrutiner undvika dubbel mappning av fysiska MDL-adresser till systemutrymme, enligt beskrivningen i steg 3, såvida de inte måste använda virtuella adresser. På så sätt används systemsidetabellposter i onödan och kan minska både drivrutinsprestanda och skalbarhet. Dessutom kan systemet krascha om det får slut på sidtabellposter, eftersom de flesta äldre drivrutiner inte kan hantera den här situationen.

Den aktuella användartrådens buffertar och själva tråden är garanterade att endast finnas i fysiskt minne när tråden är aktuell. För den tråd som visas i föregående bild kan innehållet i användarbufferten bläddras ut till sekundär lagring medan en annan processs trådar körs. När en annan processs tråd körs kan det fysiska systemminnet för den begärande trådens buffert skrivas över om inte minneshanteraren har låst och bevarat motsvarande fysiska sidor som innehåller den ursprungliga trådens buffert.

Den ursprungliga trådens virtuella adresser för bufferten förblir dock inte synliga medan en annan tråd är aktuell, även om minneshanteraren bevarar buffertens fysiska sidor. Drivrutiner kan därför inte använda en virtuell adress som returneras av MmGetMdlVirtualAddress för att komma åt minnet. Anropare av den här rutinen måste skicka sina resultat till MapTransfer- (tillsammans med IRP:s MdlAddress- pekare) för att kunna överföra data med hjälp av paketbaserat system eller DMA för busshanterare.