Udostępnij przez


Wprowadzenie do obiektów dyspozytora jądra

Jądro definiuje zestaw typów obiektów nazywanych obiektami dyspozytora jądra lub po prostu obiektami dyspozytora. Obiekty dyspozytora obejmują obiekty czasomierza, obiekty zdarzeń, obiekty semafora, obiekty mutex i obiekty wątku.

Sterowniki mogą używać obiektów dyspozytora jako mechanizmów synchronizacji w niearbitralnym kontekście wątku podczas wykonywania na poziomie IRQL równym PASSIVE_LEVEL.

Stany obiektów dyspozytora

Każdy typ obiektu dyspozytora zdefiniowanego przez jądro ma stan Zasygnalizowany lub Niezasygnalizowany.

Grupa wątków może synchronizować swoje operacje, jeśli jeden lub więcej wątków wywołuje KeWaitForSingleObject, KeWaitForMutexObject lub KeWaitForMultipleObjects. Te funkcje przyjmują wskaźniki obiektów dyspozytora jako dane wejściowe i czekają, aż kolejna rutyna lub wątek ustawia jeden lub więcej obiektów dyspozytora do stanu Signaled.

Gdy wątek wywołuje KeWaitForSingleObject w celu oczekiwania na obiekt dyspozytora (lub KeWaitForMutexObject dla muteksu), wątek jest umieszczany w stanie oczekiwania, aż obiekt dyspozytora zostanie ustawiony na stan Signaled. Wątek może wywołać KeWaitForMultipleObjects, aby czekać na ustawienie stanu 'Signaled' w przypadku dowolnego z obiektów lub wszystkich obiektów w zestawie dyspozytora.

Za każdym razem, gdy obiekt dyspozytora jest ustawiony na stan Signaled, jądro zmienia stan każdego wątku czekającego na gotowość tego obiektu. (Czasomierze synchronizacji i zdarzenia synchronizacji są wyjątkami od tej reguły; gdy zdarzenie synchronizacji lub czasomierz jest sygnalizowany, tylko jeden oczekujący wątek zostaje ustawiony w stan gotowości. Aby uzyskać więcej informacji, zobacz Obiekty czasomierza i DPC oraz obiekty zdarzeń.) Wątek w stanie gotowości zostanie zaplanowany do uruchomienia zgodnie z bieżącym priorytetem wątku według czasu wykonywania i bieżącą dostępnością procesorów dla dowolnego wątku z tym priorytetem.

Kiedy sterowniki mogą czekać na obiekty dyspozytora?

Ogólnie rzecz biorąc, sterowniki mogą czekać, aż obiekty dyspozytora zostaną ustawione tylko wtedy, gdy co najmniej jeden z następujących warunków jest spełniony:

  • Sterownik jest wykonywany w niearbitralnym kontekście wątku.

    Oznacza to, że można zidentyfikować wątek, który wejdzie w stan oczekiwania. W praktyce jedynymi procedurami sterowników wykonywanymi w kontekście wątku niearbitralnym są DriverEntry, AddDevice, Reinitialize i Rozładuj procedury każdego sterownika, a także procedury dyspozytorkie sterowników najwyższego poziomu. Wszystkie te procedury są wywoływane bezpośrednio przez system.

  • Sterownik wykonuje całkowicie synchroniczne żądanie we/wy.

    Oznacza to, że żaden sterownik nie kolejkuje żadnych operacji podczas obsługi żądania we/wy, a żaden sterownik nie zwraca się do momentu zakończenia obsługi żądania przez sterownik poniżej.

Ponadto sterownik nie może wprowadzić stanu oczekiwania, jeśli jest wykonywany na poziomie IRQL równym lub wyższym niż DISPATCH_LEVEL.

Na podstawie tych ograniczeń należy użyć następujących reguł:

  • DriverEntry, AddDevice, Reinitialize i Unload rutiny każdego sterownika mogą czekać na obiekty dyspozytora.

  • Procedury wysyłania sterownika najwyższego poziomu mogą czekać na obiekty dyspozytora.

  • Procedury wysyłania sterowników niższego poziomu mogą czekać na obiekty wysyłania, jeśli operacja we/wy jest synchroniczna, taka jak tworzenie, opróżnianie, zamykanie i zamykanie operacji, niektóre operacje sterowania we/wy urządzenia oraz operacje pnP i zasilania.

  • Procedury obsługi sterowników niższego poziomu nie mogą czekać na obiekt dyspozytora podczas zakończenia asynchronicznych operacji we/wy.

  • Procedura sterownika wykonująca w DISPATCH_LEVEL IRQL lub powyżej nie może czekać na ustawienie obiektu dyspozytora na stan Sygnał.

  • Sterownik nie może próbować czekać na ustawienie obiektu dyspozytora na stan Sygnał na zakończenie operacji transferu do lub z urządzenia stronicowania.

  • Procedury wysyłania żądań przez sterowniki przetwarzają żądania odczytu i zapisu i zwykle nie mogą czekać na przestawienie obiektu dyspozytora w stan zasygnalizowany.

  • Procedura wysyłania dla żądania sterowania we/wy urządzenia może czekać, aż obiekt dyspozycyjny zostanie ustawiony w stan Zasygnalizowany tylko wtedy, gdy typ transferu dla kodu sterowania we/wy to METHOD_BUFFERED.

  • Sterowniki miniportów SCSI nie powinny używać obiektów dyspozytora jądra. Sterowniki miniportów SCSI powinny wywoływać tylko rutyny wsparcia sterownika portu SCSI.

Każda inna standardowa rutyna sterownika jest wykonywana w kontekście dowolnego bieżącego wątku: tego wątku, który akurat jest bieżący, gdy rutyna sterownika jest wywoływana w celu przetworzenia zakolejkowanej operacji lub obsługi przerwań urządzenia. Ponadto większość standardowych procedur sterowników jest uruchamiana na podniesionym poziomie IRQL, albo na poziomie DISPATCH_LEVEL, albo dla sterowników urządzeń, na poziomie DIRQL.

W razie potrzeby sterownik może utworzyć dedykowany wątek urządzenia, który może poczekać na inne procedury sterownika (z wyjątkiem procedury ISR lub SynchCritSection), aby ustawić obiekt dyspozytora do stanu sygnalizowania i resetować do stanu Not-Signaled.

Ogólnie rzecz biorąc, jeśli spodziewasz się, że nowy sterownik urządzenia często będzie musiał się zatrzymać na dłużej niż 50 mikrosekund podczas oczekiwania na zmiany stanu urządzenia podczas operacji we/wy, rozważ zaimplementowanie sterownika z wątkiem dedykowanym urządzeniu. Jeśli sterownik urządzenia jest również sterownikiem najwyższego poziomu, rozważ użycie wątków procesu roboczego systemu i zaimplementowanie co najmniej jednej procedury wywołania zwrotnego wątku roboczego. Zobacz PsCreateSystemThread oraz Zarządzanie kolejkami połączonymi za pomocą wątku Driver-Created.