Udostępnij przez


Wstrzykiwanie awarii oparte na stosie

Uwaga Instrukcje włączania tej funkcji dotyczą tylko zestawu WDK dla systemu Windows 8. W systemie Windows 8.1 ta funkcja została zintegrowana z weryfikatorem sterowników. Na komputerach z systemem Windows 8.1 użyj opcji Symulacja systematycznych niskich zasobów.

Opcja Wstrzykiwanie błędów opartych na stosie wprowadza błędy zasobów w sterownikach trybu jądra. Ta opcja używa specjalnego sterownika, KmAutoFail.sys, w połączeniu z narzędziem Driver Verifier, aby testować ścieżki obsługi błędów sterownika. Testowanie tych ścieżek było historycznie bardzo trudne. Opcja Iniekcja awarii opartej na stosie wprowadza błędy zasobów w przewidywalny sposób, co sprawia, że znalezione problemy są możliwe do odtworzenia. Ponieważ ścieżki błędów są łatwe do odtworzenia, ułatwia również weryfikowanie poprawek tych problemów.

Aby ułatwić określenie głównej przyczyny błędu, podano rozszerzenie debugera, które może określić dokładnie, które błędy zostały wprowadzone i w jakiej kolejności.

Gdy opcja Wstrzykiwanie błędów na stosie jest włączona dla określonego sterownika, przechwytuje niektóre wywołania z tego sterownika do jądra i Ndis.sys. Iniekcja błędów oparta na stosie analizuje stos wywołań—w szczególności część stosu, która pochodzi od sterownika, dla którego jest ona włączona. Jeśli jest to pierwszy raz, kiedy kiedykolwiek widział ten stos, wywołanie zakończy się niepowodzeniem zgodnie z semantyką tego wywołania. W przeciwnym razie, jeśli zobaczyło to wywołanie wcześniej, przepuści je bez zmian. Iniekcja błędów oparta na stosie zawiera logikę umożliwiającą radzenie sobie z sytuacją, w której sterownik może być wielokrotnie ładowany i odładowywany. Rozpozna, że stos wywołań jest taki sam, nawet jeśli sterownik zostanie ponownie załadowany do innej lokalizacji pamięci.

Aktywowanie tej opcji

Możesz aktywować funkcję wstrzykiwania błędów opartych na stosie dla jednego lub większej liczby sterowników podczas wdrażania sterownika na komputerze testowym. Podczas konfigurowania właściwości weryfikatora sterowników dla projektów pakietów sterownikówmożna wybrać opcję Iniekcja błędów opartych na stosie. Aby aktywować lub dezaktywować opcję Iniekcji błędów opartej na stosie, musisz ponownie uruchomić komputer. Można również uruchomić narzędzie testowe, aby włączyć Weryfikator sterowników i tę funkcję na komputerze testowym.

Ważne Po aktywowaniu wstrzykiwania błędów opartych na stosie na komputerze testowym upewnij się, że nie wybierasz również symulacji niskich zasobów.

  • Wykorzystanie strony właściwości weryfikatora sterowników

    1. Otwórz strony właściwości pakietu sterowników. Kliknij prawym przyciskiem myszy projekt pakietu sterownika w Eksploratorze rozwiązań i wybierz pozycję Właściwości .
    2. Na stronach właściwości pakietu sterowników kliknij Właściwości konfiguracji, kliknij Instalacja sterownika, a następnie kliknij Weryfikator sterownika.
    3. Wybierz pozycję Włącz weryfikator sterowników. Po włączeniu weryfikatora sterowników na komputerze testowym można włączyć weryfikatora sterowników dla wszystkich sterowników na komputerze, tylko dla projektu sterownika lub dla listy określonych sterowników.
    4. W obszarze iniekcja błędów opartych na stosiewybierz (sprawdź) iniekcję błędów opartych na stosie.
    5. Kliknij Zastosuj lub OK.
    6. Aby uzyskać więcej informacji, zobacz Wdrażanie sterownika na komputerze testowym. Aby aktywować tę opcję, należy ponownie uruchomić komputer testowy.
  • Korzystanie z testu weryfikatora sterowników do włączania i wyłączania

    1. Możesz również włączyć Weryfikator sterowników, uruchamiając test narzędziowy. Postępuj zgodnie z instrukcjami opisanymi w Jak przetestować sterownik w czasie wykonywania przy użyciu programu Visual Studio. W kategorii testów Wszystkie testy\Weryfikator sterownika wybierz Włącz weryfikator sterownika (może być wymagany ponowny rozruch) i Wyłącz weryfikator sterownika (może być wymagany ponowny rozruch).

    2. Wybierz opcje Weryfikatora sterowników, klikając nazwę testu Włącz weryfikator sterowników (wymagany możliwy ponowny rozruch) w oknie Grupy Testów Sterowników.

    3. Wybierz (sprawdź) Iniekcja błędów opartych na stosie.

    4. Po dodaniu tych testów do grupy testowej można zapisać grupę testową. Aby włączyć iniekcję błędów opartych na stosie, uruchom test Włącz weryfikator sterowników ( możliwy ponowny rozruch wymagany) na komputerze skonfigurowanym do testowania.

      Aby dezaktywować Weryfikator sterowników, uruchom test Wyłącz Weryfikator sterowników (może być wymagany ponowny rozruch).

przy użyciu opcji Iniekcja błędów opartych na stosie

Jedną z ważnych kwestii podczas testowania z wykorzystaniem iniekcji błędów opartych na stosie jest to, że większość usterek, które zostaną wykryte, spowoduje sprawdzenie błędu systemu. Może to okazać się nieco bolesne, jeśli sterownik jest sterownikiem uruchamianym przy rozruchu. W związku z tym automatycznie wyłączymy iniekcję błędów opartych na stosie, jeśli weryfikator sterownika jest wyłączony. Oznacza to, że można wyłączyć iniekcję błędów opartych na stosie w czasie rozruchu z debugera, wyłączając weryfikatora sterownika za pomocą polecenia !weryfikator –wyłącz.

Jeśli to możliwe, na potrzeby początkowych testów z wykorzystaniem iniekcji błędów opartej na stosie, skonfiguruj sterownik tak, aby nie był ładowany podczas rozruchu. Następnie można przeprowadzić proste testy obciążeniowe i rozładowujące. Wiele błędów wykrywanych przez Stack Based Failure Injection występuje podczas inicjalizacji lub sprzątania. Wielokrotne ładowanie i zwalnianie sterownika jest dobrym sposobem na ich znalezienie.

Po wprowadzeniu wszelkich poprawek niezbędnych do pomyślnego przeprowadzenia testów zwolnienia obciążenia można przejść do testowania opartego na protokole IOCTL, pełnego testowania funkcjonalnego i wreszcie testowania obciążenia. Ogólnie rzecz biorąc, jeśli wykonasz ten test progresji, nie odkryjesz wielu nowych problemów podczas testowania obciążenia, ponieważ większość ścieżek kodu została już wykonana przed tym.

Korzystanie z rozszerzenia debugera SBFI (Stack Based Failure Injection)

Większość problemów związanych z iniekcją błędów opartą na stosie prowadzi do kontroli błędów. Aby ułatwić ustalenie przyczyny tych błędów kodu, zestaw narzędzi WDK udostępnia rozszerzenie debuggera do iniekcji błędów opartej na stosie i niezbędne symbole. Procedura instalacji zainstaluje oba komponenty w systemie debugera. Domyślną lokalizacją jest C:\Program Files (x86)\Windows Kits\8.0\Debuggers\<arch>.

Aby uruchomić rozszerzenie debugera

  • W wierszu polecenia debugera wpisz następujące polecenie: !<ścieżka>\kmautofaildbg.dll.autofail. Na przykład przy założeniu, że rozszerzenia debugera są zainstalowane w lokalizacji c:\dbgext, a plik kmautofail.pdb znajduje się w ścieżce symboli, należy wprowadzić następujące polecenie:

    !c:\dbgext\kmautofaildbg.dll.autofail
    

Spowoduje to przekazanie informacji do debuggera pokazującego stosy wywołań z ostatnich wstrzykniętych błędów. Każdy wpis wygląda tak jak poniższy przykład, zaczerpnięty z rzeczywistego przebiegu testu. W poniższym przykładzie iniekcja błędów oparta na stosie jest włączona dla sterownika Mydriver.sys.

Sequence: 2, Test Number: 0, Process ID: 0, Thread ID: 0
                 IRQ Level: 2, HASH: 0xea98a56083aae93c
 0xfffff8800129ed83 kmautofail!ShimHookExAllocatePoolWithTag+0x37
 0xfffff88003c77566 mydriver!AddDestination+0x66
 0xfffff88003c5eeb2 mydriver!ProcessPacketDestination+0x82
 0xfffff88003c7db82 mydriver!ProcessPacketSource+0x8b2
 0xfffff88003c5d0d8 mydriver!ForwardPackets+0xb8
 0xfffff88003c81102 mydriver!RoutePackets+0x142
 0xfffff88003c83826 mydriver!RouteNetBufferLists+0x306
 0xfffff88003c59a76 mydriver!DeviceSendPackets+0x156
 0xfffff88003c59754 mydriver!ProcessingComplete+0x4a4
 0xfffff88001b69b81 systemdriver2!ProcessEvent+0x1a1
 0xfffff88001b3edc4 systemdriver1!CallChildDriver+0x20
 0xfffff88001b3fc0a systemdriver1!ProcessEvent+0x3e
 0xfffff800c3ea6eb9 nt!KiRetireDpcList+0x209
 0xfffff800c3ea869a nt!KiIdleLoop+0x5a

W górnej części danych wyjściowych numer sekwencji zlicza liczbę wstrzykanych błędów. W tym przykładzie pokazano drugi błąd wstrzyknięcia podczas tego wykonywania testu. Identyfikator procesu to 0, więc był to proces systemowy. IRQL jest 2, więc jest to wywoływane na poziomie wysyłania.

KmAutoFail ze stosu jest sterownikiem do iniekcji błędów opartym na stosie. Nazwa funkcji KmAutoFail wskazuje, które wywołanie funkcji z Mydriver.sys zostało przechwycone, a następnie zastosowano wstrzyknięcie błędu. W tym miejscu funkcja, która nie powiodła się, była ExAllocatePoolWithTag. Wszystkie funkcje w usłudze KmAutoFail przechwytujące wywołania Ntoskrnl.sys lub Ndis.sys używają tej konwencji nazewnictwa. Następnie widzimy stos wywołań z testowanym sterownikiem (Mydriver.sys). Jest to część stosu wywołań używana do określenia unikalności stosu. Zatem każdy zrzut wpisu z rozszerzenia debugera będzie jedyny w tej części stosu wywołań. Pozostała część stosu wywołań wskazuje, kto wywołał sterownik. Głównym znaczeniem jest to, czy sterownik jest wywoływany z trybu użytkownika (za pomocą IOCTL) lub z sterownika trybu jądra.

Należy pamiętać, że jeśli sterownik zwrócił kod błędu ze swojej procedury DriverEntry, próba ponownego ładowania zwykle odbywa się w innym miejscu w pamięci. W takim przypadku stos wywołań z wcześniejszego miejsca najprawdopodobniej będzie zawierał "niepotrzebne dane" zamiast informacji o stosie ze sterownika. Ale to nie jest problem; informuje o tym, że sterownik prawidłowo obsłużył ten wstawiony błąd.

Ten następny wpis przedstawia wywołanie sterownika za pomocą IOCTL z trybu użytkownika. Zanotuj identyfikator procesu i poziom IRQ. Ponieważ Mydriver.sys jest sterownikiem filtru NDIS, IOCTL przeszedł przez Ndis.sys. pamiętaj, że nt!NtDeviceIoControlFile znajduje się na stosie. Wszystkie testy uruchamiane na sterowniku korzystającym z IOCTLs przejdą przez tę funkcję.

Sequence: 5, Test Number: 0, Process ID: 2052, Thread ID: 4588
                 IRQ Level: 0, HASH: 0xecd4650e9c25ee4
 0xfffff8800129ed83 kmautofail!ShimHookExAllocatePoolWithTag+0x37
 0xfffff88003c6fb39 mydriver!SendMultipleOids+0x41
 0xfffff88003c7157b mydriver!PvtDisconnect+0x437
 0xfffff88003c71069 mydriver!NicDisconnect+0xd9
 0xfffff88003ca3538 mydriver!NicControl+0x10c
 0xfffff88003c99625 mydriver!DeviceControl+0x4c5
 0xfffff88001559d93 NDIS!ndisDummyIrpHandler+0x73
 0xfffff88001559339 NDIS!ndisDeviceControlIrpHandler+0xc9
 0xfffff800c445cc96 nt!IovCallDriver+0x3e6
 0xfffff800c42735ae nt!IopXxxControlFile+0x7cc
 0xfffff800c4274836 nt!NtDeviceIoControlFile+0x56
 0xfffff800c3e74753 nt!KiSystemServiceCopyEnd+0x13

Analizowanie wyników iniekcji błędów opartych na stosie

Uruchamiasz testy na sterowniku i nagle napotykasz problem. Najprawdopodobniej była to kontrola usterek, ale może to być również spowodowane tym, że komputer przestał odpowiadać. Jak znaleźć przyczynę? Przy założeniu, że jest to sprawdzanie błędów, najpierw użyj powyższego rozszerzenia, aby znaleźć listę wstrzykniętych błędów, a następnie użyj polecenia debuggera: !analyze –v.

Najczęstszą przyczyną wystąpienia błędu jest brak sprawdzania tego, czy alokacja zakończyła się sukcesem. W takim przypadku stos wynikający z analizy sprawdzania błędów jest prawdopodobnie prawie identyczny z tym z ostatniej wstrzykniętej awarii. W pewnym momencie po nieudanej alokacji (często w następnym wierszu) sterownik uzyska dostęp do wskaźnika o wartości null. Ten typ usterki jest bardzo łatwy do naprawienia. Czasami alokacja kończąca się niepowodzeniem jest jedna lub dwie pozycje wyżej na liście, ale ten typ jest nadal bardzo łatwy do znalezienia i naprawienia.

Drugie najczęstsze sprawdzenie błędów występuje podczas sprzątania. W takim przypadku sterownik prawdopodobnie wykrył błąd alokacji i przystąpił do czyszczenia, ale podczas tego procesu sterownik nie sprawdził wskaźnika i ponownie uzyskał dostęp do wskaźnika o wartości null. Podobny przypadek to sytuacja, w której czyszczenie można wywołać dwa razy. Jeśli funkcja usuwania nie ustawi wskaźnika do struktury na wartość null po jej zwolnieniu, przy kolejnym wywołaniu funkcji usuwania spróbuje zwolnić strukturę po raz drugi, co doprowadzi do sprawdzenia błędów systemowych.

Błędy, które powodują, że komputer przestaje odpowiadać, są trudniejsze do zdiagnozowania, ale procedura ich debugowania jest podobna. Te błędy są często spowodowane przez problemy z liczbą odwołań lub spinlockiem. Na szczęście Weryfikator sterowników przechwyci wiele problemów związanych z "spin lockiem", zanim doprowadzą one do komplikacji. W takich przypadkach włamaj się do debugera i użyj rozszerzenia debugera, aby zrzucić listę błędów, które zostały wprowadzone przez iniekcję błędów opartych na stosie. Krótki przegląd kodu wokół najnowszych niepowodzeń może pokazać licznik referencji, który jest zarejestrowany przed awarią, ale nie jest zwalniany po. Jeśli nie, poszukaj wątku w sterowniku, który czeka na blokadę spinową, lub dla jakiejkolwiek liczby referencji, która jest oczywiście błędna.