Udostępnij przez


Kontrolowanie wątków i procesów

Aby zapoznać się z omówieniem wątków i procesów w a module debugera, zobacz Wątki i procesy.

W przypadku wystąpienia zdarzenia wątek zdarzenia i proces zdarzenia są ustawione na wątek i proces (system operacyjny lub wirtualny), w którym wystąpiło zdarzenie. Można je znaleźć odpowiednio przy użyciu metod GetEventThread i GetEventProcess.

Niejawne wątki i procesy

W debugowaniu w trybie jądra silnik debugera użyje niejawnego procesu, aby określić, która wirtualna przestrzeń adresowa ma być używana podczas przekładania adresów wirtualnych na fizyczne — na przykład w metodach VirtualToPhysical i ReadVirtual. W przypadku wystąpienia zdarzenia niejawny proces jest ustawiony na bieżący proces.

Proces niejawny można zmienić przy użyciu polecenia SetImplicitProcessDataOffset. Aby określić niejawny proces, użyj polecenia GetImplicitProcessDataOffset.

Nuta Podczas ustawiania punktów przerwania podczas sesji debugowania jądra na żywo aparat debugera przekaże wirtualny adres punktu przerwania do obiektu docelowego, a element docelowy ustawi punkt przerwania. W takim przypadku podczas obsługi punktu przerwania jest używany tylko kontekst procesu obiektu docelowego; wartość niejawnego procesu jest nieistotna.

W debugowaniu w trybie jądra aparat debugera użyje niejawnego wątku , aby określić niektóre rejestry obiektu docelowego. Obejmuje to stos procesora (zobacz GetStackOffset), przesunięcie ramki (zobacz GetFrameOffset) i przesunięcie instrukcji (zobacz GetInstructionOffset). Gdy wystąpi zdarzenie, niejawny wątek jest przypisany do bieżącego wątku.

Niejawny wątek może zostać zmieniony przy użyciu polecenia SetImplicitThreadDataOffset. Aby określić niejawny wątek, użyj polecenia GetImplicitThreadDataOffset.

Nie wszystkie rejestry są określane przez niejawny wątek. Niektóre rejestry pozostaną takie same po zmianie niejawnego wątku.

Ostrzeżenie Niejawny proces i niejawny wątek są niezależne. Jeśli niejawny wątek nie należy do niejawnego procesu, wówczas stan użytkownika i sesji dla niejawnego wątku będzie znajdować się w niewłaściwej wirtualnej przestrzeni adresowej i próby uzyskania dostępu do tych informacji spowodują błędy lub podają nieprawidłowe wyniki. Ten problem nie występuje podczas uzyskiwania dostępu do pamięci jądra, ponieważ adresy pamięci jądra są stałe we wszystkich wirtualnych przestrzeniach adresowych. W związku z tym informacje dotyczące niejawnego wątku znajdującego się w pamięci jądra mogą być dostępne niezależnie od niejawnego procesu.

Wątki

Identyfikator wątku silnika jest używany przez mechanizm debugera do identyfikowania każdego wątku systemu operacyjnego i każdego wątku wirtualnego dla celu.

Gdy obiekt docelowy jest zatrzymany, każdy wątek ma również indeks względem procesu, do którego należy. W przypadku dowolnego procesu indeks pierwszego wątku w procesie wynosi zero, a indeks ostatniego wątku jest liczbą wątków w procesie minus jeden. Liczbę wątków w bieżącym procesie można znaleźć za pomocą polecenia GetNumberThreads. Łączną liczbę wątków we wszystkich procesach w bieżącym celu można znaleźć, używając polecenia GetTotalNumberThreads.

Identyfikator wątku aparatu i identyfikator wątku systemowego dla jednego lub więcej wątków w bieżącym procesie można znaleźć na podstawie ich indeksu za pomocą funkcji GetThreadIdsByIndex.

Aparat przechowuje kilka informacji o każdym wątku. Informacje te mogą być odpytywane dla bieżącego wątku i mogą służyć do znalezienia identyfikatora wątku silnika dla tego wątku.

identyfikator wątku systemowego (tylko debugowanie w trybie użytkownika)
Identyfikator wątku systemowego bieżącego wątku można znaleźć za pomocą polecenia GetCurrentThreadSystemId. Dla danego identyfikatora wątku systemowego odpowiedni identyfikator wątku aparatu można znaleźć za pomocą polecenia GetThreadIdBySystemId.

blok środowiska wątkowego (TEB)
Adres TEB bieżącego wątku można znaleźć za pomocą polecenia GetCurrentThreadTeb. Dla danego adresu TEB odpowiedni identyfikator wątku silnika można znaleźć za pomocą polecenia GetThreadIdByTeb. W debugowaniu w trybie jądra, TEB wątku (wirtualnego) jest równy TEB wątku systemowego, który był uruchomiony na odpowiednim procesorze, kiedy wystąpiło ostatnie zdarzenie.

przesunięcie danych
W przypadku debugowania w trybie użytkownika przesunięcie danych wątku (systemowego) jest lokalizacją TEB dla tego wątku. W debugowaniu w trybie jądra, przesunięcie danych wątku (wirtualnego) odnosi się do struktury KTHREAD odpowiadającej wątkowi systemowemu, który był uruchomiony na odpowiednim procesorze w momencie wystąpienia ostatniego zdarzenia. Przesunięcie danych bieżącego wątku można znaleźć za pomocą polecenia GetCurrentThreadDataOffset. Dla danego przesunięcia danych odpowiedni identyfikator wątku aparatu można znaleźć przy użyciu polecenia GetThreadIdByDataOffset.

uchwyt systemowy
Uchwyt systemowy bieżącego wątku można znaleźć za pomocą polecenia GetCurrentThreadHandle. Dla danego uchwytu systemu można znaleźć odpowiedni identyfikator wątku aparatu za pomocą polecenia GetThreadIdByHandle. W debugowaniu w trybie jądra jest tworzony sztuczny uchwyt dla każdego procesu (wirtualnego). Ten uchwyt może być używany tylko z zapytaniami interfejsu API debugera.

Procesy

Identyfikator procesu silnika jest używany przez silnik debugera do identyfikowania każdego procesu systemu operacyjnego i każdego procesu wirtualnego dla celu.

Gdy obiekt docelowy jest zatrzymany, każdy proces ma indeks względem obiektu docelowego. Indeks pierwszego procesu w docelowym obiekcie wynosi zero, a indeks ostatniego procesu to liczba procesów w obiekcie docelowym minus jeden. Liczbę procesów w bieżącym elemencie docelowym można znaleźć za pomocą metody GetNumberProcesses.

Identyfikator procesu mechanizmu i identyfikator procesu systemu dla co najmniej jednego wątku w bieżącym celu można znaleźć według indeksu za pomocą polecenia GetProcessIdsByIndex.

Aparat przechowuje kilka informacji o każdym procesie. Ta informacja może być odpytywana dla bieżącego procesu i może służyć do znalezienia identyfikatora ID procesu silnika dla procesu.

identyfikator procesu systemowego (tylko debugowanie w trybie użytkownika)
Identyfikator procesu systemowego bieżącego procesu można znaleźć za pomocą polecenia GetCurrentProcessSystemId. Dla danego identyfikatora procesu systemu można znaleźć odpowiedni identyfikator procesu aparatu za pomocą GetProcessIdBySystemId.

blok środowiska przetwarzania (PEB)
Adres PEB dla bieżącego procesu można znaleźć za pomocą polecenia GetCurrentProcessPeb. Dla danego adresu PEB odpowiedni identyfikator procesu silnika można znaleźć używając GetProcessIdByPeb. W debugowaniu w trybie jądra PEB (wirtualnego) procesu jest PEB procesu systemowego, który był uruchomiony, gdy miało miejsce ostatnie zdarzenie.

przesunięcie danych
W przypadku debugowania w trybie użytkownika przesunięcie danych procesu (systemowego) jest lokalizacją PEB tego procesu. W debugowaniu w trybie jądra, przesunięcie danych wirtualnego procesu jest określone przez strukturę KPROCESS dla procesu systemowego, który działał, gdy wystąpiło ostatnie zdarzenie. Przesunięcie danych bieżącego procesu można znaleźć za pomocą polecenia GetCurrentProcessDataOffset. Dla danego przesunięcia danych odpowiedni identyfikator procesu silnika można znaleźć, używając GetProcessIdByDataOffset.

uchwyt systemowy
Dojście systemowe bieżącego procesu można znaleźć za pomocą polecenia GetCurrentProcessHandle. Dla danego uchwytu systemu można znaleźć odpowiedni identyfikator procesu aparatu za pomocą polecenia GetProcessIdByHandle. W debugowaniu w trybie jądra dla procesu (wirtualnego) jest tworzony sztuczny uchwyt. Ten uchwyt może być używany tylko z zapytaniami aparatu debugera.

Zdarzenia

Podczas dynamicznego debugowania w trybie użytkownika za każdym razem, gdy wątek zostanie utworzony lub wyjdą w obiekcie docelowym, generowane są zdarzenia debugowania create-thread i exit-thread. Te zdarzenia powodują wywołania metod zwrotnych IDebugEventCallbacks::CreateThread i IDebugEventCallbacks::ExitThread.

Podczas dynamicznego debugowania w trybie użytkownika, za każdym razem gdy proces zostaje utworzony lub zakończony w docelowym procesie, generowane są zdarzenia debugowania związane z tworzeniem i zakończeniem procesu. Te zdarzenia powodują wywołania metod wywołań IDebugEventCallbacks::CreateProcess i IDebugEventCallbacks::ExitProcess .

Aby uzyskać więcej informacji na temat zdarzeń, zobacz Monitorowanie zdarzeń.

Dodatkowe informacje

Aby uzyskać więcej informacji na temat wątków i procesów, w tym struktur TEB, KTHREAD, PEB i KPROCESS, zobacz Microsoft Windows Internals by David Solomon i Mark Russinovich.