Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tej sekcji omówiono wytyczne dotyczące implementowania procedury Anulowania i obsługi anulowalnych IRP. Aby uzyskać więcej informacji na temat obsługi anulowalnych IRP, zobacz Przebieg sterowania w przypadku kolejkowania IRP Cancel-Safe.
Ogólne wytyczne dotyczące wszystkich procedur anulowania
Menedżer I/O posiada blokadę spin anulowania za każdym razem, gdy wywołuje procedurę Anuluj sterownika. W związku z tym każda rutyna Anuluj musi:
Wywołaj metodę IoReleaseCancelSpinLock przed zwróceniem kontrolki.
Nie wywołaj IoAcquireCancelSpinLock, chyba że najpierw wywołuje IoReleaseCancelSpinLock.
Wykonaj wzajemne wywołanie funkcji IoReleaseCancelSpinLock dla każdego wywołania, które wykonuje do IoAcquireCancelSpinLock.
Za każdym razem, gdy rutynowe anulowanie wywołuje metodę IoReleaseCancelSpinLock, należy przekazać kod IRQL zwrócony przez najnowsze wywołanie metody IoAcquireCancelSpinLock. W przypadku zwolnienia blokady spin uzyskanej przez menedżera we/wy (i przechowywanej, gdy została wywołana rutyna Anuluj), rutyna Cancel musi przekazać Irp-CancelIrql>.
Sterownik nie może wywoływać procedur zewnętrznych (takich jak IoCompleteRequest) podczas trzymania spinlocka, ponieważ może dojść do zakleszczenia.
Używanie kolejek zdefiniowanych przez menedżera we/wy
Jeśli sterownik nie zarządza własnymi wewnętrznymi kolejkami IRP, jego procedura Cancel jest wywoływana przy użyciu przychodzącego IRP, który może być jednym z następujących elementów:
CurrentIrp w wejściowym obiekcie urządzenia docelowego
Wpis w kolejce urządzenia skojarzony z obiektem urządzenia docelowego
Jeśli sterownik nie zarządza własnymi wewnętrznymi kolejkami IRP, jego procedura Cancel powinna wywołać KeRemoveEntryDeviceQueue z wejściowym IRP, aby sprawdzić, czy jest to wpis w kolejce urządzenia powiązanej z obiektem urządzenia docelowego. Rutyna Anulowania sterownika nie może wywołaćKeRemoveDeviceQueue lub KeRemoveByKeyDeviceQueue, ponieważ nie można założyć, że dane IRP znajduje się w konkretnej pozycji w kolejce urządzenia.
Bieżący stan wejściowego protokołu IRP
Jeśli procedura Anuluj jest wywoływana z IRP, dla którego sterownik rozpoczął już przetwarzanie we/wy, a żądanie zostanie wkrótce ukończone, procedura Anuluj powinna zwolnić blokadę spin anulowania i zwrócić kontrolę.
Jeśli bieżący stan wejściowego protokołu IRP to Oczekiwanie, należy wykonać następującą procedurę Anulowania :
Ustaw blok stanu I/O dla wejściowego protokołu IRP z wartością STATUS_CANCELLED dla kolumny Status i zero dla kolumny Informacje.
Zwolnij wszystkie blokady spinowe, w tym systemową blokadę anulowania spinów.
Wywołaj IoCompleteRequest z podanym IRP.
Utrzymywanie IRP w stanie anulowalnym
Każda procedura sterownika, która zawiera protokół IRP w stanie umożliwiającym anulowanie, musi wywołać metodę IoMarkIrpPending i wywołać metodę IoSetCancelRoutine , aby ustawić punkt wejścia procedury Cancel w IRP. Tylko wtedy ta rutyna sterownika może wywołać dodatkowe rutyny wsparcia, takie jak IoStartPacket, IoAllocateController lub ExInterlockedInsert..List.
Każda procedura sterownika, która przetwarza anulowalne IRP, musi sprawdzić, czy IRP zostało już anulowane, zanim rozpocznie operacje w celu spełnienia żądania. Procedura musi wywołać metodę IoSetCancelRoutine , aby zresetować punkt wejścia procedury Cancel na wartość NULL w IRP. Dopiero wtedy ta rutyna może rozpocząć przetwarzanie we/wy dla wejściowego protokołu IRP.
Procedura może wymagać zresetowania punktu wejścia dla procedury Anuluj w IRP, jeśli również przekazuje IRP do dalszego przetwarzania przez inne procedury sterowników i te IRP mogą być przechowywane w stanie anulowalnym.
Każdy sterownik wyższego poziomu, który utrzymuje IRP w stanie umożliwiającym anulowanie, musi ustawić jego punkt wejścia Cancel na NULL, zanim przekaże go do następnego niższego sterownika za pomocą IoCallDriver.
Anulowanie IRP
Każdy sterownik wyższego poziomu może wywołać IoCancelIrp z IRP, który został przydzielony i przekazany do dalszego przetwarzania przez sterowniki niższego poziomu. Jednak taki sterownik nie może przyjąć, że dany protokół IRP zostanie ukończony z STATUS_CANCELLED przez niższe sterowniki.
Synchronizacja
Sterownik może (lub musi, w zależności od swojego projektu) zachować dodatkowe informacje o stanie w rozszerzeniu urządzenia, aby śledzić anulowalny stan IRP. Jeśli ten stan jest współużytkowany przez rutyny kierowców działające w środowisku IRQL <= DISPATCH_LEVEL, udostępnione dane powinny być chronione za pomocą spin lock przydzielonego i zainicjowanego przez sterownik.
Kierowca powinien starannie zarządzać przejęciami i zwolnieniami blokady spin systemu anulującego oraz własnych blokad spin. Powinien trzymać blokadę spin systemu w możliwie najkrótszych interwałach. Przed uzyskaniem dostępu do anulowalnego IRP, taki sterownik powinien zawsze sprawdzać wartość zwracaną IoSetCancelRoutine, aby określić, czy rutyna Anulowanie jest już uruchomiona (lub ma zostać uruchomiona); jeśli tak, powinien pozwolić, aby rutyna Anulowanie ukończyła IRP.
Jeśli sterownik urządzenia przechowuje informacje o stanie cancelowalnych IRP, które różne procedury sterowników współdzielą z jego ISR, te inne procedury muszą synchronizować dostęp do udostępnianego stanu z ISR. Tylko procedura SynchCritSection dostarczana przez sterownik może uzyskiwać dostęp do informacji o stanie udostępnianych przez isR w bezpieczny sposób wieloprocesorowy.
Aby uzyskać więcej informacji, zobacz Techniki synchronizacji.