Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I det här avsnittet beskrivs riktlinjer för att implementera en Avbryt-rutin och hantera avbrytbara IRP:er. Mer information om hur du hanterar avbrytbara IRP:er finns under Kontrollflödet för Cancel-Safe IRP-köer.
Allmänna riktlinjer för alla avbrytningsrutiner
I/O-hanteraren innehar avbryt-spinnlåset varje gång den anropar en drivrutins Cancel-rutin. Därför måste varje Cancel-rutin :
Anropa IoReleaseCancelSpinLock innan den återlämnar kontrollen.
Anropa inte IoAcquireCancelSpinLock om det inte anropar IoReleaseCancelSpinLock först.
Gör ett ömsesidigt anrop till IoReleaseCancelSpinLock för varje anrop det gör till IoAcquireCancelSpinLock.
Varje gång Avbryt-rutinen anropar IoReleaseCancelSpinLock måste den vidarebefordra den IRQL som returneras av det senaste anropet till IoAcquireCancelSpinLock. När du släpper det spinnlås som förvärvats av I/O-hanteraren (och hölls när Cancel-rutinen anropades) måste Cancel-rutinen passera Irp->CancelIrql.
En drivrutin får inte anropa externa rutiner (till exempel IoCompleteRequest) när den håller ett spinlock eftersom ett dödläge kan uppstå.
Använda kön som definierats av I/O-hanteraren
Om inte en drivrutin hanterar sina egna interna köer med IRPs, anropas dess Cancel-rutin med en inkommande IRP som kan vara en av följande:
CurrentIrp i målenhetsobjektet för indata
En post i kön för enheter som är associerad med målenhetsobjektet
Om inte en drivrutin hanterar sina egna interna köer av IRP:er bör dess Cancel-rutin anropa KeRemoveEntryDeviceQueue med IRP för inmatning för att testa om det är en post i enhetskön som är associerad med målenhetsobjektet. Drivrutinens Cancel-rutin kan inte anropa KeRemoveDeviceQueue eller KeRemoveByKeyDeviceQueue eftersom den inte kan anta att den angivna IRP:n befinner sig på någon viss plats i enhetskön.
Aktuellt tillstånd för ingående IRP
Om en Cancel-rutin anropas med en IRP som drivrutinen redan har börjat I/O-bearbeta och begäran snart kommer att slutföras, bör Cancel-rutinen släppa systemets avbrytande snurrlås och återge kontroll.
Om det aktuella tillståndet för indata-IRP är Väntande måste en Avbryt-rutin göra följande:
Ange IRP:s I/O-statusblock för indata med STATUS_CANCELLED för Status och noll för Information.
Släpp alla spinnlås som den håller i, inklusive systemets avbrutna spinnlås.
Anropa IoCompleteRequest med den angivna IRP:n.
Hålla IRP:er i ett avbrytbar tillstånd
Alla drivrutinsrutiner som innehåller en IRP i ett avbrytbar tillstånd måste anropa IoMarkIrpPending och måste anropa IoSetCancelRoutine för att ange startpunkten för avbrytningsrutinen i IRP. Endast då kan den drivrutinen anropa ytterligare supportrutiner som IoStartPacket, IoAllocateController eller en ExInterlockedInsert..Listrutin.
Alla drivrutiner som därefter bearbetar avbrytbara IRP:er måste kontrollera om en IRP redan har avbrutits innan den påbörjar åtgärder för att uppfylla begäran. Rutinen måste anropa IoSetCancelRoutine för att återställa startpunkten för cancel-rutinen till NULL i IRP. Först då kan den rutinen börja sin I/O-bearbetning för indata-IRP.
En rutin kan behöva återställa startpunkten för en Cancel-rutin i en IRP om den också skickar IRP:er för vidare bearbetning av andra drivrutiner och dessa IRP:er kan hållas i ett avbrytbara tillstånd.
Alla drivrutiner på högre nivå som har en IRP i ett avbrytbara tillstånd måste återställa ingångspunkten Avbryt till NULL innan den skickar IRP till nästa lägre drivrutin med IoCallDriver.
Avbrytande av en IRP
Alla drivrutiner på högre nivå kan anropa IoCancelIrp med en IRP som den har allokerat och vidarebefordrat för vidare bearbetning av drivrutiner på lägre nivå. En sådan drivrutin kan dock inte förutsätta att den angivna IRP:en slutförs med STATUS_CANCELLED av lägre drivrutiner.
Synkronisering
En drivrutin kan (eller måste, beroende på dess design) behålla ytterligare tillståndsinformation i enhetsutvidgningen för att spåra IRP:ers avbrytbara status. Om det här tillståndet delas av drivrutinsrutiner som körs på IRQL <= DISPATCH_LEVEL bör delade data skyddas med ett drivrutinsallokerat och initierat spinnlås.
Drivrutinen bör hantera sina inlåsningar och frisläppningar av systemets avbryt spinnlås och sina egna spinnlås noggrant. Den bör ha kontroll över systemets avbryta spinnlås under så korta intervall som möjligt. Innan du får åtkomst till en avbruten IRP bör en sådan drivrutin alltid kontrollera returvärdet för IoSetCancelRoutine för att avgöra om Cancel-rutinen redan körs (eller är på väg att köras). I så fall bör rutinen Avbryt slutföra IRP.
Om en enhetsdrivrutin behåller tillståndsinformation om avbrytbara IRP:er som olika drivrutinsrutiner delar med dess ISR, måste dessa rutiner synkronisera åtkomsten till det delade tillståndet med ISR. Endast en synchCritSection-rutin som tillhandahålls av drivrutinen kan komma åt tillståndsinformation som delas med ISR på ett sätt som är säkert för flera processorer.
Mer information finns i Synkroniseringstekniker.