Dela via


Konfigurera och använda enhetsköer

En drivrutin konfigurerar ett objekt i enhetskön genom att anropa KeInitializeDeviceQueue vid initiering av drivrutiner eller enheter. Efter att ha startat dess enhet(er) infogar drivrutinen IRP:er i den här kön genom att anropa KeInsertDeviceQueue eller KeInsertByKeyDeviceQueue. Följande bild illustrerar dessa anrop.

konfigurera och använda enhetsköer.

Som den här bilden visar måste drivrutinen tillhandahålla lagringen för ett enhetsköobjekt, som måste vara residerande. Drivrutiner som konfigurerar ett enhetsköobjekt tillhandahåller vanligtvis nödvändig lagring i enhetstillägget för ett enhetsobjekt som skapats av drivrutinen, men lagringen kan finnas i ett kontrollanttillägg om drivrutinen använder ett kontrollantobjekt eller i en icke-siddelad pool som allokeras av drivrutinen.

Om drivrutinen tillhandahåller lagring för enhetsköobjektet i ett enhetstillägg anropas KeInitializeDeviceQueue när du har skapat enhetsobjektet och innan enheten startas. Med andra ord kan drivrutinen initiera kön från sin AddDevice-rutin eller när den hanterar en PnP-begäran IRP_MN_START_DEVICE. I anropet till KeInitializeDeviceQueue skickar drivrutinen en pekare till lagringen som den tillhandahåller för enhetsköobjektet.

När enheten har startat kan drivrutinen infoga en IRP i enhetskön genom att anropa KeInsertDeviceQueue, som placerar IRP i könens slut, eller KeInsertByKeyDeviceQueue, som placerar IRP i kön enligt ett drivrutinsbestämt SortKey-värde, enligt föregående bild.

Var och en av dessa supportrutiner returnerar ett booleskt värde som anger om IRP infogades i kön. Var och en av dessa anrop anger också tillståndet för enhetens köobjekt till Upptagen om kön för närvarande är tom (Not-Busy). Men om kön är tom (Not-Busy) infogar varken KeInsertXxxDeviceQueue-rutinen IRP i kön. I stället anger den tillståndet för enhetsköobjektet till Upptagen och returnerar FALSE. Eftersom IRP inte har placerats i kö måste drivrutinen vidarebefordra den till en annan drivrutinsrutin för vidare bearbetning.

När du konfigurerar kompletterande enhetsköer följer du den här implementeringsguiden:

När ett anrop till KeInsertXxxDeviceQueue returnerar FALSE måste anroparen skicka den IRP som den försökte köa på för vidare bearbetning till en annan drivrutin. Anropet till KeInsertXxxDeviceQueue ändrar dock tillståndet för enhetsköobjektet till Upptagen, så nästa IRP som ska komma in infogas i kön om inte drivrutinen anropar KeRemoveXxxDeviceQueue först.

När enhetsköobjektets tillstånd är inställt på Upptagen kan drivrutinen ta bort en IRP från kön för vidare bearbetning eller återställa tillståndet till Not-Busy genom att anropa någon av följande supportfunktioner:

  • KeRemoveDeviceQueue för att ta bort IRP i början av kön

  • KeRemoveByKeyDeviceQueue för att ta bort en IRP som valts enligt ett drivrutinsbestämt SortKey-värde

  • KeRemoveEntryDeviceQueue för att ta bort en viss IRP i kön eller för att avgöra om en viss IRP finns i kön

    KeRemoveEntryDeviceQueue returnerar ett booleskt värde som anger om IRP fanns i enhetskön.

Att anropa någon av dessa rutiner för att ta bort en post från en enhetskö som är tom men upptagen ändrar kötillståndet till Inte upptagen.

Varje enhetsköobjekt skyddas av ett inbyggt executive spin lock (som inte visas i figuren Använda ett objekt i enhetskön). Därför kan en drivrutin infoga IRPs i kön och ta bort dem på ett multiprocessor-säkert sätt från alla drivrutinsrutiner som körs på IRQL mindre än eller lika med DISPATCH_LEVEL. På grund av denna IRQL-begränsning kan en drivrutin inte anropa någon KeXxxDeviceQueue-rutin från sina ISR- eller SynchCritSection-rutiner , som körs på DIRQL.

Mer information finns i Hantera maskinvaruprioriteringar och spinnlås . Information om IRQL-krav för en specifik supportrutin finns på rutinens referenssida.