DZWONEK

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Nazwa
Nazwisko
Jak chcesz przeczytać The Bell
Bez spamu

Podczas wykonywania kodu trybu jądra o najwyższym priorytecie nie można uruchomić żadnego innego kodu na tym procesorze. Oczywiście, jeśli zbyt duże ilości kodu programu są wykonywane przy zbyt wysokich wartościach IRQL, nieuchronnie doprowadzi to do ogólnej degradacji systemu.

Aby rozwiązać ten typ problemu, kod trybu jądra musi być zaprojektowany tak, aby uniknąć długotrwałego działania na wysokich poziomach IRQL. Jednym z najważniejszych elementów tej strategii są odroczone wywołania procedur (DPC) - odroczone wywołania procedur.

Operacja DPC

Schemat korzystania z odroczonych wywołań proceduralnych pozwala na zbudowanie procesu wykonywania w taki sposób, aby można było wykonać zadanie zaplanowany kod działający na wysokim poziomie IRQL, ale jeszcze nie jest wykonane ... To odroczenie jest przydatne, jeśli w sterowniku występuje usługa przerwania i nie ma powodu, aby blokować wykonanie innego kodu przy niższym IRQL. Innymi słowy, gdy leczenie tej sytuacji można bezboleśnie odłożyć na później.

System operacyjny utrzymuje kolejkę obiektów DPC w celu śledzenia żądań wywołania procedur DPC.

Na początek ograniczymy się do rozważenia prostszego przypadku pracy z procedurami DPC przeznaczonymi do użycia w połączeniu z procedurami obsługi przerwań. Ten rodzaj procedur DPC otrzymał w literaturze specjalną nazwę DpcForIsr.

Obiekt DPC do użycia w procedurach przerwań jest tworzony na żądanie IoInitializeDpcRequestzwykle wykonywane w ramach procedur uruchamiania sterownika. To wywołanie rejestruje procedurę oferowaną przez sterownik DpcForIsr i kojarzy ją z tworzonym obiektem - dość powszechna technika w systemie Windows. Należy szczególnie zauważyć, że obiekt DPC utworzony przez to wywołanie pozostanie w trzewiach systemu operacyjnego, niedostępny dla twórcy sterownika. (Różnica między DpcForIsr a innymi procedurami DPC polega tylko na tym, że praca z tą ostatnią odbywa się za pomocą wywołań Ke ... Dpc, a utworzone dla nich obiekty DPC są dostępne dla programisty sterownika).

Jeśli sterownik zarejestrował swoją procedurę DpcForIsr, to podczas przetwarzania przerwania ISR przez procedurę odpowiedni obiekt DPC można umieścić w kolejce systemowej DPC (w rzeczywistości żądanie wywołania tej procedury DpcForIsr później) - wywołując IoRequestDpc... Procedura DpcForIsr później zakończy przetwarzanie żądania odebranego przez ISR przez procedurę, co zostanie wykonane w mniej krytycznych warunkach i przy niskim IRQL.

Ogólnie rzecz biorąc, funkcjonowanie procedur DPC (w tym przypadku DpcForIsr) składa się z następujących operacji:

  • Kiedy fragment kodu programu działający na wysokim IRQL (sprzętowym) chce zaplanować wykonanie niektórych prac przy niskim IRQL, dodaje obiekt DPC do kolejki wywołań procedur oczekujących w systemie.
  • Wcześniej czy później IRQL procesora spadnie poniżej DISPATCH_LEVEL, a praca opóźniona przez przerwanie jest obsługiwana przez funkcję DPC. Dyspozytor DPC pobiera każdy obiekt DPC z kolejki i wywołuje odpowiednią funkcję, której wskaźnik jest przechowywany w tym obiekcie. Ta funkcja jest wywoływana, gdy procesor działa na poziomie DISPATCH_LEVEL.

Cechy mechanizmu DPC

Ogólnie praca z odroczonymi wywołaniami proceduralnymi nie jest trudna, ponieważ systemy operacyjne Windows 2000 / XP / Server 2003 oferują duży zestaw wywołań systemowych, które ukrywają wiele szczegółów procesu. Należy jednak podkreślić dwa najbardziej zwodnicze aspekty pracy z DPC.

Po pierwsze, system Windows NT 5 nakłada ograniczenie polegające na tym, że pojedyncze wystąpienie obiektu DPC można umieścić w systemowej kolejce DPC w określonych odstępach czasu. Próby umieszczenia obiektu w kolejce DPC, który dokładnie pasuje do już istniejącego, są odrzucane. W rezultacie następuje tylko jedno wywołanie procedury DPC, nawet jeśli kierowca czeka na zakończenie dwóch połączeń. Może się to zdarzyć, jeśli dwa przerwania zostały wyzwolone przez obsługiwane urządzenie, a przetwarzanie pierwszego odroczonego wywołania proceduralnego jeszcze się nie rozpoczęło. Pierwsza instancja obiektu DPC nadal znajduje się w kolejce, podczas gdy sterownik rozpoczął już przetwarzanie drugiego przerwania.

Konstrukcja sterownika powinna przewidywać taki przebieg mechanizmu DPC. Być może należy podać dodatkowy licznik żądań DPC lub sterownik może zaimplementować własną implementację kolejki żądań. W czasie rzeczywistej leniwej procedury możesz sprawdzić licznik i własną kolejkę żądań, aby określić, jaką konkretną pracę należy wykonać.

Po drugie, podczas pracy na platformach wieloprocesorowych występują poważne problemy z synchronizacją. Załóżmy, że kod programu działający na jednym procesorze wykonuje usługę przerwania i planuje wywołanie procedury DPC (umieszczenie obiektu DPC w kolejce systemowej). Jednak nawet zanim przerwanie zostanie w pełni przetworzone, inny procesor może rozpocząć przetwarzanie obiektu DPC umieszczonego w kolejce systemowej. W ten sposób powstaje sytuacja, w której kod obsługi przerwania jest wykonywany równolegle i jednocześnie z kodem procedury DPC. Z tego powodu konieczne jest zapewnienie środków dla niezawodnej synchronizacji dostępu kodu programu procedury DPC do zasobów wykorzystywanych w połączeniu z procedurą obsługi przerwań sterownika.

Jeśli przyjrzysz się uważnie liście parametrów połączeń IoInitializeDpcRequest i IoRequestDpc (zaprojektowany do pracy z procedurami DpcForIsr), łatwo zauważyć, że obiekt DPC jest „powiązany” z obiektem urządzenia. Podczas umieszczania tego obiektu w kolejce DPC w czasie procedury ISR wskazywany jest również obiekt urządzenia. Daje to pewność, wywołanie, do którego konkretnej procedury DPC jest „uporządkowane” przez procedurę ISR (korelacja według obiektu urządzenia). Sugeruje to również, że sterownik, który utworzył kilka obiektów urządzenia (raczej rzadki przypadek), może również wykorzystać kilka procedur DpcForIsr - po jednej dla każdego obiektu urządzenia.

Systemowy mechanizm DPC zapobiega jednoczesnemu przetwarzaniu obiektów DPC z kolejki systemowej, nawet w konfiguracjach wieloprocesorowych. Tak więc, jeśli zasoby są współdzielone przez kilka odroczonych procedur, nie ma potrzeby martwić się o synchronizację dostępu do nich.

Powyżej omówiono użycie procedur DPC do zakończenia obsługi przerwań, czyli DpcForIsr. Jednak procedury DPC można wykorzystać w inny sposób, na przykład w połączeniu z licznikami czasu do organizowania oczekiwania. Aby to zrobić, za pomocą wywołania zostanie utworzony obiekt DPC KeInitializeDPCktóry wiąże ten obiekt z procedurą DPC zawartą w sterowniku. Następnie możesz ustawić limit czasu w poprzednio zainicjowanym (używając KeInitializeTimer lub KeInitializeEx) obiekt timera. Połączenie służy do ustawienia interwału oczekiwania KeSetTimer, do którego jako jeden z parametrów należy przekazać wskaźnik do zainicjowanego obiektu DPC. Po wygaśnięciu limitu czasu DPC obiekt zostanie dodany do systemowej kolejki DPC, a powiązana z nim procedura DPC zostanie wywołana tak szybko, jak to możliwe. DPC tego drugiego typu są określane w dokumentacji DDK jako „niestandardowe DPC”. (To użycie procedur DPC sprawia, że \u200b\u200bsą one bardzo podobne do wywołań APC w trybie użytkownika).

Aby umieścić w systemowej kolejce DPC obiektów odpowiadających drugiemu typowi procedur DPC (nie związanych z przerwaniami), użyj wywołania KeInsertQueueDpc... W związku z tym kod inicjatora wywołania musi działać na poziomie IRQL co najmniej DISPATCH_LEVEL.

Aby wyczyścić kolejkę systemową DPC z niestandardowych procedur DPC, na przykład, jeśli kierowca musi natychmiast zakończyć pracę, zadzwoń KeRemoveQueueDpcktóry można wywołać z dowolnego kodu poziomu IRQL.

Obsługa przerwań czasowych

Każdy komputer ma zegar sprzętowy lub zegar systemowy, który generuje przerwanie sprzętowe w stałych odstępach czasu. Odstęp czasu między sąsiednimi przerwaniami nazywany jest taktem procesora lub po prostu tikiem (takt procesora, takt zegara). Zwykle zegar systemowy obsługuje wiele wartości taktu, ale w systemie UNIX ta wartość jest zwykle ustawiona na 10 milisekund, chociaż ta wartość może się różnić w zależności od wersji systemu operacyjnego. Większość systemów przechowuje tę wartość w stałej HZ, która jest zdefiniowana w pliku nagłówkowym Na przykład dla taktu 10 milisekund wartość Hz jest ustawiana na 100.

Program obsługi przerwań jądra jest wywoływany przez sprzętowe przerwanie czasowe, które zwykle ma najwyższy priorytet. Zatem obsługa przerwań powinna zająć minimalną ilość czasu. Ogólnie rzecz biorąc, przewodnik rozwiązuje następujące zadania:

1. Aktualizacja statystyk użycia procesora dla bieżącego procesu

2. Wykonywanie szeregu funkcji związanych z procesami planowania, takich jak ponowne obliczanie priorytetów i sprawdzanie przedziału czasowego dla procesu

3. Sprawdzenie, czy limit procesora dla tego procesu nie został przekroczony i wysłanie sygnału SIGXCPU do tego procesu, jeśli

4. Aktualizacja czasu systemowego (pory dnia) i innych powiązanych timerów

5. Obsługa połączeń opóźnionych

6. Obsługa alarmów

7. W razie potrzeby włącz procesy systemowe, takie jak menedżer stron i zamiana

Niektórych zadań nie trzeba wykonywać za każdym razem. Większość systemów wprowadza główną notację tick, która pojawia się przy każdym ticku, w zależności od konkretnej wersji systemu. Pewien zestaw funkcji jest wykonywany tylko w przypadku dużych tików. Na przykład przelicza priorytety co 4 tiki, a SVR4 przetwarza i budzi procesy systemowe raz na sekundę McKusick M.K., Neville-Neil J.W. . FreeBSD: architektura i implementacja . - M.: KUDITS-OBRAZ, 2006. - 800 p ...

Opóźnione połączenia

Odroczone wywołanie definiuje funkcję, która zostanie wywołana przez jądro po pewnym czasie. Na przykład w SVR4 każdy podsystem jądra może zarejestrować oczekujące wywołanie, takie jak to:

int co_ID \u003d timeout (void (* fn) (), caddr_t arg, long delta)

gdzie fn definiuje adres funkcji, która ma zostać wywołana, podczas gdy argument arg zostanie do niej przekazany, a samo wywołanie zostanie wykonane przez tiki delta. Jądro wywołuje fn () w kontekście systemowym, więc funkcja odroczonego wywołania nie powinna mieć dostępu do przestrzeni adresowej bieżącego procesu (ponieważ nie ma z tym nic wspólnego), a także nie powinna przechodzić w stan uśpienia.

Połączenia odroczone służą do realizacji wielu funkcji, na przykład:

1. Wykonywanie szeregu funkcji harmonogramu i podsystemu zarządzania pamięcią.

2. Wykonywanie szeregu funkcji sterownika urządzenia dla zdarzeń, które mogą się nie powieść. Przykładem jest moduł protokołu TCP, który w ten sposób implementuje retransmisję pakietów sieciowych po przekroczeniu limitu czasu.

3. Urządzenia odpytywające, które nie obsługują przerwań.

Należy zauważyć, że funkcje odroczonego wywołania są wykonywane w kontekście systemu, a nie w kontekście przerwania. Funkcje te są wywoływane nie przez program obsługi przerwań czasowych, ale przez oddzielną procedurę obsługi oczekującego wywołania, która jest uruchamiana po przetworzeniu przerwania czasowego. Podczas przetwarzania przerwania timera system sprawdza, czy konieczne jest uruchomienie pewnych funkcji odroczonych połączeń i ustawia dla nich odpowiednią flagę. Z kolei odroczona obsługa połączeń sprawdza flagi i uruchamia niezbędną w kontekście systemowym McKusick MK, Neville-Neil JV FreeBSD: architekturę i implementację. - M.: KUDITS-OBRAZ, 2006. - 800 p ...

Kontekst procesu

Kontekst procesu obejmuje zawartość przestrzeni adresowej zadania przydzielonej procesowi, a także zawartość rejestrów sprzętowych związanych z procesem i struktur danych jądra. Z formalnego punktu widzenia kontekst procesu łączy kontekst użytkownika, kontekst rejestru i kontekst systemu.

Kontekst użytkownika składa się z instrukcji i danych procesu, stosu zadań i zawartości pamięci współużytkowanej w adresach wirtualnych procesu. Te części wirtualnej przestrzeni adresowej procesu, które są okresowo nieobecne w pamięci RAM z powodu wyładowania lub wymiany strony, są również uwzględnione w kontekście użytkownika.

Kontekst rejestru składa się z następujących komponentów:

1. Licznik instrukcji wskazujący adres następnej instrukcji do wykonania przez centralny procesor; ten adres jest adresem wirtualnym w przestrzeni jądra lub przestrzeni zadań.

2. Rejestr stanu procesora (PS), który wskazuje stan sprzętu maszyny w odniesieniu do procesu. Na przykład rejestr PS zwykle zawiera podpola, które wskazują, czy wynik ostatniego obliczenia jest zerowy, dodatni czy ujemny, czy rejestr jest przepełniony zestawem przenoszonego bitu itp. Operacje wpływające na ustawienie rejestru PS są wykonywane dla oddzielnego procesu, ponieważ wtedy rejestr PS zawiera stan sprzętu maszyny w odniesieniu do procesu. Inne ważne podpola rejestru PS wskazują aktualny poziom przerwań procesora, a także aktualny i poprzednie tryby wykonywania procesu (tryb jądra / zadania). Wartość podpola bieżącego trybu wykonywania procesu określa, czy proces może wykonywać polecenia uprzywilejowane i uzyskiwać dostęp do przestrzeni adresowej jądra.

3. Wskaźnik wierzchołka stosu, który zawiera adres kolejnego elementu jądra lub stosu zadań, zgodnie z trybem wykonywania procesu. W zależności od architektury maszyny, wskaźnik stosu wskazuje następny wolny element stosu lub ostatnio używany element. Kierunek zwiększania stosu (w kierunku wyższych lub niższych adresów) również zależy od architektury maszyny, ale dla nas te pytania są teraz nieistotne.

4. Rejestry ogólnego przeznaczenia, które zawierają informacje generowane przez proces podczas jego realizacji.

Kontekst systemowy procesu ma „część statyczną” (pierwsze trzy pozycje z poniższej listy) i „część dynamiczną” (ostatnie dwa elementy). Przez cały czas wykonywania proces ma zawsze jedną statyczną część kontekstu systemu, ale może mieć zmienną liczbę części dynamicznych. Dynamiczna część kontekstu systemowego może być reprezentowana jako stos, którego elementami są poziomy kontekstu, które są wypychane na stos przez jądro lub zdejmowane ze stosu, gdy występują różne zdarzenia. Kontekst systemu obejmuje następujące komponenty:

1. Wpis w tabeli procesów opisujący stan procesu (rozdział 6.1) i zawierający różne informacje sterujące, do których jądro ma zawsze dostęp.

2. Część przestrzeni adresowej zadania przydzielona procesowi, w której przechowywane są informacje sterujące o procesie, dostępne tylko w kontekście procesu. Ogólne parametry kontrolne, takie jak priorytet procesu, są przechowywane w tabeli procesów, ponieważ muszą być dostępne poza kontekstem procesu.

3. Wpisy w prywatnej tabeli obszaru procesu, tabelach obszaru ogólnego i tabelach stron, wymagane do konwersji adresów wirtualnych na adresy fizyczne, a tym samym opisują polecenia, dane, stos i inne obszary procesu. Jeśli wiele procesów ma wspólne obszary, obszary te są częścią kontekstu każdego procesu, ponieważ każdy proces działa z tymi obszarami niezależnie od innych procesów. Zadania zarządzania pamięcią obejmują identyfikowanie nierezydentnych części wirtualnej przestrzeni adresowej procesu.

4. Stos jądra, który przechowuje rekordy procedur jądra, jeśli proces działa w trybie jądra. Chociaż wszystkie procesy używają tych samych programów jądra, każdy proces ma własną kopię stosu jądra do przechowywania indywidualnych wywołań funkcji jądra. Na przykład przypuśćmy, że jeden proces wywołuje funkcję creat i zatrzymuje się w oczekiwaniu na przypisanie nowego indeksu, a inny proces wywołuje funkcję odczytu i zatrzymuje się w oczekiwaniu na zakończenie transferu z dysku do pamięci. Oba procesy mają dostęp do funkcji jądra, a każdy z nich ma oddzielny stos, który przechowuje sekwencję wykonanych wywołań. Jądro musi być w stanie odtworzyć zawartość stosu jądra i położenie wskaźnika stosu, aby wznowić wykonywanie procesu w trybie jądra. W różnych systemach stos jądra często znajduje się w przestrzeni procesu, ale ten stos jest logicznie niezależny, a zatem może zmieścić się w oddzielnym obszarze pamięci. Gdy proces działa w trybie zadania, odpowiadający mu stos jądra jest pusty.

5. Dynamiczna część kontekstu systemowego procesu, składająca się z kilku poziomów i mająca postać stosu, który jest uwalniany od elementów w kolejności odwrotnej do ich nadejścia. Każdy poziom kontekstu systemu zawiera informacje potrzebne do przywrócenia poprzedniego poziomu i obejmuje kontekst rejestru z poprzedniego poziomu.

Jądro umieszcza poziom kontekstu na stosie, gdy występuje przerwanie, gdy wywoływana jest funkcja systemowa lub gdy zmienia się kontekst procesu. Warstwa kontekstu jest zdejmowana ze stosu, gdy przetwarzane jest przerwanie, gdy proces powraca do trybu zadań po wykonaniu funkcji systemowej lub gdy następuje przełączenie kontekstu. Zatem przełączanie kontekstu pociąga za sobą zarówno wypychanie poziomu kontekstu na stos, jak i zdejmowanie go ze stosu: jądro wypycha poziom kontekstu starego procesu na stos i zdejmuje poziom kontekstu nowego procesu ze stosu. Informacje wymagane do odtworzenia bieżącego poziomu kontekstu są przechowywane w pozycji tabeli procesów Robachevsky A.M. UNIX . - SPb .: BHV - Petersburgu , 2002. -- 528 od . .

Chociaż większość przerwań jest generowana na poziomie sprzętowym, jądro systemu Windows generuje przerwania programowe dla różnych zadań, w tym następujących:

  • uruchomienie wysyłania wątków;
  • przetwarzanie przerwań niekrytycznych czasowo;
  • obsługa wygaśnięcia timera;
  • asynchroniczne wykonanie procedury w kontekście określonego wątku;
  • obsługa asynchronicznych operacji we / wy.

Zadania te omówiono w poniższych sekcjach.

Wysłane przerwania lub przerwania odroczonego wywołania procedury (DeferredProcedureCall, DPC). Gdy wątek nie może już kontynuować wykonywania, być może dlatego, że został zakończony lub dlatego, że dobrowolnie wszedł w stan oczekiwania, jądro bezpośrednio wywołuje dyspozytora, aby natychmiast przełączyć kontekst.

Ale czasami jądro dowiaduje się, że zmiana harmonogramu musi nastąpić, gdy wykonywany kod jest głęboko zagnieżdżony. W takiej sytuacji jądro żąda wysłania, ale odkłada ją do czasu zakończenia bieżącej pracy. Użycie programowego przerwania DPC jest wygodnym sposobem implementacji tego opóźnienia.

Jądro zawsze podnosi IRQL CPU do DPC / dispatch lub wyższego, gdy musi zsynchronizować dostęp do typowych struktur jądra. To blokuje dodatkowe przerwania programowe i wysyłanie wątków. Kiedy jądro wykryje, że potrzebna jest wysyłka, żąda przerwania DPC / wysyłki, ale procesor opóźnia przerwanie, ponieważ IRQL jest na tym poziomie lub powyżej.

Kiedy jądro kończy swoją bieżącą pracę, procesor widzi, że zamierza zepchnąć IRQL poniżej poziomu DPC / wysyłki i sprawdza oczekujące przerwania wysyłania. Jeśli takie przerwania są obecne, IRQL jest obniżany do poziomu DPC / wysyłki i obsługiwane są przerwania wysyłania. Włączenie dyspozytora wątków za pomocą przerwania programowego jest sposobem na odroczenie wysyłania do momentu, gdy odpowiednie okoliczności będą odpowiednie. Ale system Windows używa przerwań programowych, aby odroczyć również inne typy przetwarzania.

Oprócz wysyłania wątków jądro obsługuje na tym poziomie IRQL i odroczone wywołania procedur (DPC). DPC to funkcja, która wykonuje zadanie systemowe, które jest mniej krytyczne czasowo niż bieżące zadanie.

Funkcje nazywane są odroczonymi, ponieważ nie wymagają natychmiastowego wykonania.

Odroczone wywołania procedur umożliwiają systemowi operacyjnemu wygenerowanie przerwania i wykonanie funkcji systemowej w trybie jądra.

Jądro używa wywołań DPC do obsługi wygaśnięcia liczników czasu (i wolnych wątków, które czekają na wygaśnięcie liczników) oraz do zmiany harmonogramu użycia procesora po wygaśnięciu przydzielonego czasu wątku (kwant wątku). Sterowniki urządzeń używają wywołań DPC do obsługi przerwań. Aby zapewnić terminową obsługę przerwań programowych, system Windows współpracuje ze sterownikami urządzeń, aby zachować wartości IRQL poniżej IRQL urządzenia. Jednym ze sposobów osiągnięcia tego celu jest wykonanie przez ISR sterowników urządzeń minimalnej pracy niezbędnej do powiadomienia ich urządzeń, utrzymania tymczasowego stanu przerwania i opóźnienia przesyłania danych lub przetwarzania innych przerwań o mniejszym znaczeniu czasowym w celu wykonania w wywołaniach DPC na poziomie DPC / IRQL. wysyłka.

Wywołanie DPC jest reprezentowane przez obiekt DPC, który jest obiektem kontroli jądra, który jest niewidoczny dla programów w trybie użytkownika, ale widoczny dla sterowników urządzeń i innego kodu systemowego. Najważniejszą informacją zawartą w obiekcie DPC jest adres funkcji systemowej, którą jądro wywoła podczas obsługi przerwania DPC. Oczekujące DPC są przechowywane w kolejkach zarządzanych przez jądro, po jednej kolejce na każdy procesor.

Nazywa się to kolejkami DPC. Aby zażądać DPC, kod systemowy wywołuje jądro w celu zainicjowania obiektu DPC, a następnie umieszcza ten obiekt w kolejce DPC.

Domyślnie jądro umieszcza obiekty DPC na końcu kolejki DPC procesora, na którym zażądano DPC (zwykle jest to procesor, na którym działa ISR). Jednak sterownik urządzenia może zastąpić to zachowanie, określając priorytet DPC (niski, średni, powyżej średniego lub wysokiego, który domyślnie ma średni priorytet) i kierując DPC do określonego procesora. Wywołanie DPC skierowane do określonego procesora jest znane jako docelowy DPC. Jeśli DPC ma wysoki priorytet, jądro umieszcza obiekt DPC na początku kolejki, w przeciwnym razie dla wszystkich innych priorytetów umieszcza obiekt na końcu kolejki.

Jądro obsługuje wywołania DPC, gdy IRQL procesora ma zamiar zmienić wersję DPC / dispatch IRQL lub wyższą na niższą IRQL (APC lub pasywną). System Windows utrzymuje IRQL na poziomie DPC / wysyłki i pobiera obiekty DPC z kolejki bieżącego procesora aż do jej wyczerpania (to znaczy, że jądro „zużywa” kolejkę), wywołując po kolei każdą funkcję DPC. Jądro pozwoli, aby poziom IRQL spadł poniżej poziomu DPC / wysyłki i pozwoli na kontynuowanie normalnego wykonywania wątku tylko wtedy, gdy kolejka zostanie wyczerpana. Przetwarzanie DPC przedstawiono na rysunku Priorytety DPC mogą wpływać na zachowanie systemu w inny sposób.

Zazwyczaj jądro inicjuje użycie kolejki DPC z przerwaniem DPC / dispatch. Jądro generuje takie przerwanie tylko wtedy, gdy wywołanie DPC jest kierowane do aktualnego procesora (tego, na którym działa ISR), a DPC ma priorytet wyższy niż niski. Jeśli DPC ma niski priorytet, jądro zażąda przerwania tylko wtedy, gdy liczba oczekujących żądań DPC procesora przekroczy próg lub jeśli liczba wywołań DPC żądanych przez procesor w danym oknie czasowym jest niska.

Dostarczanie połączeń DPC

Jeśli wywołanie DPC jest skierowane do innego procesora niż ten, na którym działa ISR, a priorytet DPC jest wysoki lub średnio-wysoki, jądro natychmiast sygnalizuje docelowemu procesorowi (wysyłając mu komunikat IPI) do zużycie jego kolejki DPC, ale tylko wtedy, gdy procesor docelowy jest bezczynny. Jeśli priorytet jest średni lub niski, liczba oczekujących wywołań DPC na procesorze docelowym musi przekroczyć pewien próg, aby jądro mogło wysłać przerwanie DPC / wysłanie. Wątek bezczynności systemu opróżnia również kolejkę DPC procesora, na którym jest uruchomiony. Pomimo elastyczności zapewnianej systemowi przez cele wywołań DPC i poziomy priorytetów, sterowniki urządzeń rzadko muszą zmieniać domyślne zachowanie swoich obiektów DPC. Sytuacje opróżniania kolejki DPC są podsumowane w tabeli. Jeśli spojrzysz na reguły generowania, w rzeczywistości okazuje się, że priorytety powyżej średniej i wysokie są sobie równe. Różnica pojawia się, gdy są wstawione do listy, z przerwaniami wysokiego poziomu z przodu i ponadprzeciętnymi z tyłu.

Ponieważ wątki w trybie użytkownika działają z niskim IRQL, istnieje duże prawdopodobieństwo, że wywołanie DPC przerwie normalny wątek użytkownika. Procedury DPC są wykonywane niezależnie od tego, który wątek jest uruchomiony, dlatego po uruchomieniu procedury DPC nie można założyć, czyja przestrzeń adresowa, który proces jest aktualnie wyświetlany. Procedury DPC mogą wywoływać funkcje jądra, ale nie mogą wywoływać usług systemowych, generować błędów stronicowania ani tworzyć obiektów wysyłkowych ani czekać na nie. Mogą jednak uzyskać dostęp do niestronicowanych adresów pamięci systemowej, ponieważ przestrzeń adresowa systemu jest zawsze mapowana, niezależnie od tego, jaki jest bieżący proces.

Reguły generowania przerwań DPC.

Priorytet DPCWywołanie DPC jest skierowane do procesora wykonującego
Procedura ISR
Połączenie DPC jest skierowane
do innego procesora
NiskaDługość kolejki DPC przekracza maksymalną długość kolejki DPC lub poziom żądania DPC jest poniżej minimum
Poziom żądania DPC
Środkowy
(Średni)
Jest zawszeDługość kolejki DPC przekracza maksymalną długość kolejki DPC lub system jest bezczynny
Powyżej średniej
(Średni wzrost)
Jest zawsze
WysokiJest zawszeProcesor docelowy jest bezczynny

Wywołania DPC są dostarczane głównie do sterowników urządzeń, ale są również używane przez jądro. Najczęściej jądro używa DPC do obsługi wygaśnięcia przedziału czasu. Za każdym razem, gdy zegar systemowy tyka, na poziomie IRQL zegara występuje przerwanie. Program obsługi przerwania zegara (działający na poziomie IRQL zegara) aktualizuje czas systemowy, a następnie zmniejsza licznik, który śledzi czas wykonywania bieżącego wątku.

Gdy licznik osiągnie zero, przedział czasu wątku wygaśnie, a jądro może wymagać zmiany harmonogramu czasu procesora, to znaczy wykonania zadania o niższym priorytecie, które powinno być wykonane na poziomie DPC / wysyłki IRQL.

Program obsługi przerwania zegara kolejkuje wywołanie DPC w celu zainicjowania wysyłania wątku, a następnie wychodzi i obniża IRQL procesora. Ponieważ przerwania DPC mają niższy priorytet niż przerwania urządzenia, wszelkie oczekujące przerwania urządzenia, które występują przed zakończeniem przerwania zegara, są przetwarzane przed wysłaniem przerwania DPC.

Ponieważ wywołania DPC są wykonywane niezależnie od tego, który wątek jest obecnie wykonywany w systemie (co jest bardzo podobne do przerwań), są one głównym powodem, dla którego system, na którym są wykonywane, staje się odporny na obciążenie systemów klienckich lub stacji roboczej, ponieważ nawet wątki o najwyższym priorytecie zostaną przerwane przez oczekujące wywołanie DPC.

Niektóre połączenia DPC trwają tak długo, że użytkownicy mogą zauważyć opóźnienia wideo lub audio, a nawet nietypowe spowolnienie reakcji myszy lub klawiatury, więc w przypadku sterowników z długimi połączeniami DPC system Windows obsługuje strumieniowe połączenia DPC.

Streamingowe DPC, jak sugeruje ich nazwa, są zaprojektowane do wykonywania procedury DPC na poziomie pasywnym w strumieniu z priorytetem czasu rzeczywistego (priorytet 31). Dzięki temu wywołanie DPC ma pierwszeństwo przed większością wątków w trybie użytkownika (ponieważ większość wątków aplikacji nie rozpoczyna się w zakresach priorytetów w czasie rzeczywistym). Ale dzięki temu inne przerwania, niezwiązane z wątkami wywołania DPC, wywołania APC i wątki o wyższym priorytecie mają pierwszeństwo przed tą procedurą.

Oprócz tego, że jest używany do uruchamiania dyspozytora NT (harmonogramu), IRQL dispatch_level jest również używany do obsługi odroczonych wywołań procedur (DPC). Wywołania DPC to wywołania zwrotne do podprogramów, które będą wykonywane na urządzeniu wysyłkowym IRQL. Połączenia DPC są zwykle wymagane od wyższych IRQL w celu wykonania rozszerzonego, niekrytycznego czasowo przetwarzania.

Rzućmy okiem na kilka przykładów użycia DPC. Sterowniki urządzeń Windows NT wykonują bardzo mało przetwarzania w ramach swoich procedur obsługi przerwań. Zamiast tego, gdy urządzenie jest przerywane (na poziomie DIRQL) i jego sterownik ustali, że wymagane jest złożone przetwarzanie, prosi o DPC. Żądanie DPC powoduje wywołanie określonej funkcji sterownika w IRQL dispatch_level w celu wykonania pozostałej części wymaganego przetwarzania. Wykonując to przetwarzanie na poziomie IRQL dispatch_level, sterownik spędza mniej czasu na poziomie DIRQL, a tym samym zmniejsza opóźnienie przerwań dla wszystkich innych urządzeń w systemie.

Na rys. 15 przedstawia typową sekwencję zdarzeń.

ISR najpierw żąda od DPC, a NT umieszcza obiekt DPC w kolejce docelowego procesora. W zależności od priorytetu DPC i długości kolejki DPC NT generuje przerwanie programowe DPC natychmiast lub po pewnym czasie. Gdy procesor czyści kolejkę DPC, obiekt DPC opuszcza kolejkę i sterowanie jest przekazywane do jego funkcji DPC, która kończy przerwanie, odczytując dane z urządzenia lub zapisując dane do urządzenia, które wygenerowało przerwanie.
Innym powszechnym zastosowaniem DPC są procedury czasowe. Kierowca może zażądać wykonania określonej funkcji, aby powiadomić go o upływie określonego czasu (odbywa się to za pomocą funkcji KeSetTimer ()). Program obsługi przerwań zegarowych monitoruje upływ czasu i po pewnym czasie żąda DPC dla procedury zdefiniowanej przez sterownik. Użycie DPC do powiadamiania o zegarze pozwala programowi obsługi przerwania zegara na szybki powrót, ale nadal powoduje wywołanie określonej procedury bez zbędnego opóźnienia.

Obiekty DPC

Wywołanie DPC jest opisane przez obiekt DPC. Definicja obiektu DPC (KDPC) jest wykonana w ntddk.h i jest pokazana na rys. szesnaście.

Postać: 16. Obiekt DPC

Obiekt DPC może zostać przydzielony przez sterownik z dowolnej przestrzeni niestronicowanej (takiej jak pula niestronicowana). Obiekty DPC są inicjowane za pomocą funkcji KelnitializeDpc (), której prototypem jest:

VOID KelnitializeDpc (IN PKDPC Dpc,
W PKDEFERRED ^ ROUTINE DeferredRoutine,
W PVOID DeferredContext);

Gdzie:
Dpc - Wskaźnik do obiektu DPC, który ma zostać zainicjowany; DeferredRoutine - wskaźnik do funkcji, za pomocą której należy wykonać odroczone wywołanie na poziomie IRQL DISPATCH_LEVEL. Prototyp funkcji DeferredRoutine jest następujący:

VOID (* PKDEFERRED_ROUTINE) (
W PKDPC Dpc,
W PVOID DeferredContext,
W systemie PVOIDArgumentI,
W PVOID SystemArgument2);

Gdzie:
DeferredContext - wartość do przekazania do DeferredRoutine jako parametr wraz ze wskaźnikiem do obiektu DPC i dwoma dodatkowymi parametrami.
Żądanie wykonania określonej procedury DPC jest składane przez umieszczenie obiektu DPC opisującego tę procedurę DPC w kolejce DPC określonego procesora, a następnie (zwykle) żądanie przerwania programowego w IRQL
dispatch_level. Na każdy procesor przypada jedna kolejka DPC. Procesor, do którego obiekt DPC jest umieszczony w kolejce, jest zwykle procesorem bieżącym, na którym wysyłane jest żądanie (przerwania). Sposób wyboru procesora dla konkretnego DPC omówiono w dalszej części rozdziału Charakterystyka obiektów DPC. Obiekt DPC jest umieszczany w kolejce za pomocą funkcji KelnsertQueueDpc (), której prototypem jest:

VOID KelnsertQueueDpc (IN PKDPC Dpc,
W systemie PVOIDArgument1,
W PVOID SystemArgument2);

Gdzie:
Dpc - wskazuje obiekt DPC do umieszczenia w kolejce;
SystemArgumentl, SystemArgument2 - dowolne wartości, które muszą zostać przekazane do funkcji DeferredRoutme odpowiednio jako parametry 3 i 4, wraz ze wskaźnikiem do obiektu DPC i parametrem DeferredContext określonym podczas inicjowania obiektu DPC.

Aktywacja i konserwacja DPC

Pochodzenie przerwania programowego Dispatch_level jest rozpoznawane, gdy to przerwanie staje się najwyższym oczekującym zdarzeniem IRQL oczekującym na tym procesorze. Dlatego po wywołaniu funkcji KelnsertQueueDpc (), zwykle następnym razem, gdy procesor jest gotowy do powrotu do IRQL poniżej dispatch_level, zamiast tego powróci do IRQL dispatch_level i spróbuje przetworzyć zawartość kolejki DPC.
Jak wspomniano wcześniej w tym rozdziale, IRQL DISPATCHJLEVEL jest używany zarówno do wysyłania, jak i przetwarzania kolejki DPC. W systemie NT 4.0, gdy obsługiwane jest przerwanie DISPATCH_LEVEL, najpierw obsługiwana jest cała kolejka DPC, a następnie wywoływany jest dyspozytor w celu zaplanowania uruchomienia następnego wątku. Jest to uzasadnione, ponieważ przetwarzanie wykonywane przez procedurę DPC może zmienić stan bazy danych planowania wątków, na przykład sprawiając, że poprzednio oczekujący wątek jest zdrowy.
Kolejka DPC jest obsługiwana przez Microkernel. Za każdym razem, gdy serwisowana jest kolejka DPC, przetwarzane są wszystkie pozycje kolejki DPC dla bieżącego procesora. Pojedynczo Microkernel usuwa obiekt DPC z nagłówka kolejki i wywołuje DeferredRoutine określony w obiekcie. Mikrojądro przekazuje wskaźnik do obiektu DPC, zawartość pól DeferredContext, SystemArgumentl i SystemArgument2 obiektu DPC jako parametry do funkcji DeferredRoutine.
Ponieważ kolejka DPC jest obsługiwana na IRQL dispatch_level, procedury DPC są wywoływane na IRQL dispatch_level. Ponieważ kolejka DPC jest obsługiwana za każdym razem, gdy IRQL dispatch_level jest IRQL o najwyższym priorytecie do obsłużenia (na przykład natychmiast po uruchomieniu programu obsługi przerwań i przed powrotem do przerwanego wątku użytkownika), funkcje DPC działają w dowolnym kontekście wątku. Przez kontekst dowolnego wątku rozumiemy, że DPC jest wykonywany w procesie i wątku, co może w ogóle nie mieć nic wspólnego z żądaniem, które obsługuje DPC. (Kontekst wykonania opisano bardziej szczegółowo w sekcji „Warstwowy model sterownika”).
Procedura DPC kończy przetwarzanie i zwraca. Po powrocie z podprogramu DPC, mikrojądro próbuje pobrać inny obiekt DPC z kolejki DPC i przetworzyć go. Gdy kolejka DPC jest pusta, przetwarzanie DPC kończy się. Mikrojądro przechodzi do wywołania Dispatchera (harmonogramu).

Wiele połączeń z DPC

Każdy DPC jest opisany przez określony obiekt DPC. W rezultacie za każdym razem, gdy wywoływana jest funkcja KelnsertQueueDpc () i okaże się, że przekazany do niego obiekt DPC znajduje się już w tej samej kolejce DPC, funkcja KelnsertQueueDpcQ po prostu zwraca (bez podejmowania żadnej akcji). Dlatego za każdym razem, gdy obiekt DPC znajduje się już w kolejce DPC, wszelkie kolejne próby umieszczenia tego samego obiektu DPC w kolejce przed usunięciem obiektu DPC z kolejki są ignorowane. Ma to sens, ponieważ obiekt DPC może być fizycznie włączony tylko do jednej kolejki DPC naraz.
Oczywiste pytanie może brzmieć: Co się dzieje, gdy zostanie wysłane żądanie umieszczenia obiektu DPC w kolejce, ale system już wykonuje podprogram DPC określony przez ten obiekt DPC (na tym samym lub innym procesorze)? Odpowiedź na to pytanie można znaleźć uważnie czytając poprzednią sekcję. Gdy mikrokernel obsługuje kolejkę DPC, usuwa obiekt DPC z nagłówka kolejki, a dopiero potem wywołuje podprocedurę DPC określoną przez obiekt DPC. Tak więc, gdy wywoływana jest procedura DPC, obiekt DPC został już usunięty z kolejki DPC procesora. Dlatego też, gdy żąda się umieszczenia obiektu DPG w kolejce, a system znajduje się w podprocedurze DPC określonej w tym obiekcie DPC, DPC jest umieszczany w kolejce jak zwykle.

DPC w systemach wieloprocesorowych

W przeciwieństwie do tego, co argumentowały niektóre inne źródła, i jak powinno być oczywiste z poprzedniej dyskusji, ta sama procedura DPC może działać na wielu procesorach jednocześnie. Nie ma absolutnie żadnego blokowania przez mikrojądro, aby temu zapobiec.
Rozważmy przypadek sterownika urządzenia, który ma jednocześnie wiele oczekujących żądań. Urządzenie sterownika jest przerywane na procesorze 0, program obsługi przerwań sterownika działa i żąda od DPC zakończenia obsługi przerwań. Jest to standardowa ścieżka, którą podążają sterowniki systemu Windows NT. Kiedy procedura obsługi przerwań zakończy się i system będzie gotowy do powrotu do przerwanego wątku użytkownika, IRQL procesora O jest obniżany z DIRQL, w którym ISR został wykonany, do poziomu IRQL dispatch_level. W rezultacie Mikrokernel utrzymuje kolejkę DPC, usuwając obiekt DPC sterownika i wywołując określoną w nim procedurę DPC. Procedura sterownika DPC jest teraz uruchomiona na procesorze 0.
Natychmiast po wywołaniu podprogramu sterownika DPC urządzenie ponownie generuje przerwanie. Jednak tym razem, z powodów znanych tylko sprzętowi, przerwanie jest obsługiwane na Procesorze 1. Ponownie, program obsługi przerwań sterownika żąda DPC. I znowu, kiedy procedura obsługi przerwań zakończy się, system (Procesor 1) jest gotowy do powrotu do przerwanego wątku użytkownika. Obniża to IRQL procesora 1 do poziomu IRQL dispatch_level, a mikrokernel obsługuje kolejkę DPC. Robiąc to (i nadal działając na Procesorze 1), mikrojądro usuwa obiekt sterownika DPC i wywołuje podprocedurę sterownika DPC. Procedura DPC sterownika działa teraz na Procesorze 1. Zakładając, że procedura DPC sterownika nie zakończyła jeszcze wykonywania na Procesorze 0, należy zauważyć, że ta sama procedura DPC działa teraz równolegle na obu procesorach.
Ten przykład podkreśla wagę stosowania w sterownikach prawidłowego zestawu wieloprocesorowych mechanizmów synchronizacji. W szczególności funkcja DPC powinna używać blokad spinlock w celu serializacji dostępu do dowolnych struktur danych, do których należy uzyskać dostęp jako całość, pod warunkiem, że projekt sterownika umożliwia jednoczesne wykonywanie wielu wywołań DPC.

Charakterystyka obiektów DPC

Obiekty DPC mają dwie cechy, które wpływają na sposób ich przetwarzania. Te cechy to pola Ważność i Liczba.

Znaczenie DPC

Każdy obiekt DPC ma znaczenie, które jest przechowywane w polu Ważność obiektu DPC. Wartości tego pola są wymienione w ntddk.h pod nazwami Highlmportance, Mediumlmportance i Lowlmportance. Ta wartość DPC obiektu wpływa na lokalizację w kolejce DPC, w której obiekt DPC jest umieszczony w kolejce, oraz na to, czy IRQL dispatch_level zostanie przerwany, gdy obiekt DPC zostanie umieszczony w kolejce. Funkcja KelnitializeDpc () inicjuje obiekty DPC z istotnością Mediumlmportance. Ważność obiektu DPC można ustawić za pomocą funkcji KeSetlmportanceDpc (), której prototypem jest:

VOID KeSetlmportanceDpc (W PKDPC Dpc,
W KDPCIMPORTANCE Znaczenie);

Gdzie:
Dpc - Wskaźnik do obiektu DPC, w którym należy ustawić pole Ważność;
Ważność to wartość ważności do zainstalowania w obiekcie DPC.
DPC ze średnim lub niskim statusem są umieszczane na końcu kolejki DPC. Obiekty DPC z Highlmportance są umieszczane na początku kolejki DPC.
Znaczenie obiektów DPC wpływa również na to, czy przerwanie programowe dispatch_level jest generowane, gdy obiekt DPC jest umieszczony w kolejce. Kiedy obiekt DPC z Highlmportance lub Mediumlmportance jest umieszczony w kolejce na bieżącym procesorze, zawsze generowane jest przerwanie dispatchjevel. Przerwanie dispatch_level jest generowane dla DPC Lowlmportance lub dla tych DPC, które są przeznaczone dla innego procesora niż obecny procesor, zgodnie ze złożonym (i nieudokumentowanym) algorytmem planowania.
Tabela 11 zawiera listę sytuacji, które wyzwalają zwolnienie kolejki obiektów DPC.
Większość sterowników urządzeń nigdy nie będzie musiała ustawiać ważności swoich obiektów DPC. W rzadkich przypadkach, gdy opóźnienie między żądaniem DPC a wykonaniem DPC jest nadmierne, a twórca sterownika nie jest w stanie rozwiązać opóźnienia w inny sposób, możesz spróbować ustawić obiekt DPC na Highlmportance. Zwykle jednak sterowniki urządzeń w systemie Windows NT nie zmieniają wartości DPC z domyślnej Mediumlmportance.

Tabela 11. Sytuacje wyzwalające czyszczenie kolejki DPC

Priorytet DPC

DPC działają na tym samym procesorze co ISR

DPC są wykonywane na innym procesorze

Niska

Rozmiar kolejki DPC przekracza maksimum, częstotliwość żądań DPC jest mniejsza niż minimum lub system jest bezczynny

Rozmiar kolejki DPC przekracza maksimum lub system jest bezczynny (uruchomiony wątek bezczynny)

DPC można ograniczyć do wykonania na określonym procesorze za pomocą funkcji KeSetTargetProcessorDpc (), której prototypem jest:

VOID KeSetTargetProcessorDpc (W PKDPC Dpc,
IN CCHAR Number);

Gdzie:
Dpc - wskazuje obiekt DPC, dla którego docelowy procesor powinien być zainstalowany;
Liczba to liczony od zera numer procesora, na którym DPC powinien działać.
Podobnie jak znaczenie DPC, docelowy DPC prawie nigdy nie jest ustawiany przez sterownik urządzenia. Wartość domyślna używana do wykonywania DPC na bieżącym procesorze jest prawie zawsze pożądana.
Gdy dla obiektu DPC jest zainstalowany określony procesor docelowy, ten obiekt DPC będzie zawsze umieszczany w kolejce DPC określonego procesora. Tak więc, na przykład, nawet gdy KelnsertQueueDpc () jest wywoływana na procesorze 0, obiekt DPC z procesorem 1 ustawionym jako procesor docelowy zostanie wstawiony do kolejki DPC na procesorze 1.

Jak omówiono wcześniej w tym rozdziale, DPC są najczęściej używane do zakończenia obsługi przerwań (ISR). Aby ułatwić sterownikom urządzeń żądanie od DPC wykonania funkcji ISR \u200b\u200bz ich funkcji ISR, I / O Manager definiuje specjalny DPC, który może być użyty w tym celu. Ten DPC nazywa się DpcForlsr.
Menedżer we / wy wstawia obiekt DPC do każdego tworzonego obiektu urządzenia. Ten osadzony obiekt DPC jest inicjowany przez sterownik urządzenia, zwykle przy pierwszym ładowaniu sterownika, przez wywołanie funkcji IoInitializeDpcRequest ().
IoInitializeDpcRequest () przyjmuje jako dane wejściowe wskaźnik do obiektu urządzenia, w którym osadzony jest obiekt DPC, wskaźnik do funkcji sterownika do wywołania oraz wartość kontekstu do przekazania tej funkcji. IoInitializeDpcRequest () z kolei wywołuje KelnitializeDpc () w celu zainicjowania osadzonego obiektu DPC, przekazując wskaźnik funkcji sterownika jako parametr DeferredRoutine i wartość kontekstu jako parametr DeferredContext.
Aby zażądać DPC od ISR, sterownik po prostu wywołuje loRequestDpc () przekazując wskaźnik do obiektu urządzenia. Z kolei IoRequestDpc () wywołuje KelnsertQueueDpc () na obiekcie DPC osadzonym w obiekcie urządzenia.
Ponieważ wszystkie sterowniki urządzeń mają obiekty urządzeń, a wszystkie sterowniki używające przerwań również używają DPC, użycie mechanizmu DpcForlsr Menedżera I / O jest bardzo wygodne. W rzeczywistości większość sterowników urządzeń w systemie Windows NT nigdy nie wywołuje bezpośrednio KelnitializeDpc () lub KelnsertQueueDpc (), ale zamiast tego wywołuje loInitializeDpcRequest () i IoRequestDpc ().

Obiekty zarządzania obejmują prymitywne obiekty dla wątków, przerwań, liczników czasu, synchronizacji, profilowania i dwa specjalne obiekty do implementacji DPC i APC. Obiekty DPC (Deferred Procedure Call) służą do skrócenia czasu wykonywania procedur obsługi przerwań (ISR), które są wyzwalane przez przerwanie z urządzenia. Ograniczenie czasu spędzanego na procedurach ISR zmniejsza szanse na utratę przerwania.

Sprzęt systemowy przypisuje przerwania priorytet sprzętowy. Procesor wiąże również poziom priorytetu z wykonywaną pracą. Procesor odpowiada tylko na przerwania, które mają wyższy priorytet niż ten, którego aktualnie używa. Normalny poziom priorytetu (w tym poziom priorytetu całego trybu użytkownika) to 0. Przerwania urządzenia występują na poziomie 3 lub wyższym, a ISR przerwania urządzenia zwykle działa z tym samym poziomem priorytetu co przerwanie (więc inne mniej ważne przerwania nie wystąpiło podczas przetwarzania ważniejszego przerwania).

Jeśli ISR \u200b\u200btrwa zbyt długo, obsługa przerwań o niższym priorytecie będzie opóźniona, co może spowodować utratę danych lub spowolnienie operacji we / wy systemu. W danym momencie może być uruchomionych kilka ISR, przy czym każdy kolejny ISR powstaje z przerwań o wyższym poziomie priorytetu.

Aby skrócić czas przetwarzania ISR, wykonywane są tylko krytyczne operacje, takie jak zapis wyników operacji we / wy i ponowna inicjalizacja urządzenia. Dalsze przetwarzanie przerwania jest odkładane do czasu obniżenia poziomu priorytetu procesora i zaprzestania blokowania obsługi innych przerwań. Obiekt DPC służy do reprezentowania pracy do wykonania, a ISR wywołuje warstwę jądra, aby umieścić DPC na liście DPC specyficznej dla procesora. Jeśli DPC jest pierwszy na liście, to jądro rejestruje specjalne żądanie przerwania sprzętowego dla procesora poziomu 2 (na którym NT wywołuje poziom DISPATCH). Kiedy ostatni istniejący ISR kończy pracę, poziom przerwań procesora spada poniżej 2, co odblokowuje przerwanie dla przetwarzania DPC. ISR przerwania DPC przetworzy każdy z obiektów DPC (które jądro umieściło w kolejce).

Technika wykorzystania przerwań programowych do odroczenia obsługi przerwań jest uznaną techniką zmniejszania opóźnienia ISR. UNIX i inne systemy zaczęły używać leniwego przetwarzania w latach 70. XX wieku (aby poradzić sobie z wolnym sprzętem i ograniczonymi buforami szeregowymi). ISR odebrał symbole z urządzenia i ustawił je w kolejce. Po zakończeniu przetwarzania wszystkich przerwań wysokiego poziomu, przerwanie programowe wyzwoliło ISR o niskim priorytecie w celu przetworzenia znaków (na przykład, aby zaimplementować kursor z powrotem o jedną pozycję - w tym celu do terminala został wysłany znak kontrolny, aby usunąć ostatni wyświetlany znak, a kursor cofnięty) ...

Podobnym przykładem we współczesnym systemie Windows jest klawiatura. Po naciśnięciu klawisza ISR klawiatury odczytuje kod klawisza z rejestru, a następnie ponownie włącza przerwanie klawiatury, ale nie przetwarza klawisza natychmiast. Zamiast tego używa DPC do umieszczenia w kolejce przetwarzania kodu klucza (do momentu przetworzenia wszystkich przerwań na urządzeniu, które ma być przetworzone).

Ponieważ DPC działają w warstwie 2, nie kolidują z ISR dla urządzeń, ale kolidują z żadnymi wątkami od wykonywania, dopóki wszystkie kolejkowane DPC nie zostaną zakończone, a poziom priorytetu procesora spadnie poniżej 2. Sterowniki urządzeń i system nie powinny zajmować zbyt dużo czasu. ISR lub DPC. Ponieważ strumienie nie mogą być wykonywane, ISR i DPC mogą spowalniać system i zawieszać się podczas odtwarzania muzyki (spowalniając te strumienie, które zapisują muzykę z bufora do urządzenia audio). Innym typowym przypadkiem użycia DPC jest wykonywanie procedur przerwań czasowych. Aby uniknąć blokowania wątków, zdarzenia czasomierza (które muszą działać przez długi czas) muszą kolejkować żądania do puli wątków roboczych (którą jądro utrzymuje do pracy w tle).

DZWONEK

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Nazwa
Nazwisko
Jak chcesz przeczytać The Bell
Bez spamu