jc/md/lp-01/06Kernel Tracker1 Debugging Kernel Tracker
jc/md/lp-01/06Kernel Tracker2 Objectif du chapitre Écrire un programme multithread en mode debug Explorer Kernel Tracker, outils avancé de mise au point
jc/md/lp-01/06Kernel Tracker3 DEBUG Main (1) #include "stdafx.h" DWORD WINAPI A_MAIN(LPVOID p); DWORD WINAPI B_MAIN(LPVOID p); DWORD WINAPI FIN(LPVOID p); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
jc/md/lp-01/06Kernel Tracker4 DEBUG Main (2) { DWORD dwExitCode; //Déclaration et création des événements et des threads HANDLE hEvent_A=CreateEvent( NULL,TRUE,FALSE,L"EVENT_A"); HANDLE hEvent_B=CreateEvent( NULL,TRUE,FALSE,L"EVENT_B"); HANDLE hEvent_fin=CreateEvent( NULL,TRUE,FALSE,NULL ); HANDLE hThread_Fin=CreateThread(0,0,FIN,&hEvent_fin,0,0); HANDLE hThread_A=CreateThread( 0,0, A_MAIN,&hThread_Fin, 0,0 ); HANDLE hThread_B=CreateThread( 0,0,B_MAIN,&hThread_Fin, 0,0 );
jc/md/lp-01/06Kernel Tracker5 DEBUG Main (3) //Impression des handles pour identifier les objets dans Kernel Tracker RETAILMSG(1,(TEXT("MAIN: hThread_A= %x\n"),hThread_A)); RETAILMSG(1,(TEXT("MAIN: hThread_B= %x\n"),hThread_B)); RETAILMSG(1,(TEXT("MAIN: hThread_Fin= %x\n"),hThread_Fin)); RETAILMSG(1,(TEXT("MAIN: hEvent_A= %x\n"),hEvent_A)); RETAILMSG(1,(TEXT("MAIN: hEvent_B= %x\n"),hEvent_B)); RETAILMSG(1,(TEXT("MAIN: hEvent_fin= %x\n"),hEvent_fin)); //Déclenchement de lévénement A SetEvent(hEvent_A);
jc/md/lp-01/06Kernel Tracker6 DEBUG Main (4) //Attente du signal de fin puis de la fin… de A et de B WaitForSingleObject(hEvent_fin,INFINITE); //Attente…fin while(GetExitCodeThread(hThread_A,&dwExitCode), dwExitCode == STILL_ACTIVE) Sleep(0); //…tant que thread A… pas fini while(GetExitCodeThread(hThread_B,&dwExitCode), dwExitCode == STILL_ACTIVE) Sleep(0); //…tant que thread B… pas fini
jc/md/lp-01/06Kernel Tracker7 DEBUG Main (5) //Fermeture de tous les handles créés CloseHandle(hThread_A); CloseHandle(hThread_B); CloseHandle(hThread_Fin); CloseHandle(hEvent_A); CloseHandle(hEvent_B); CloseHandle(hEvent_fin); RETAILMSG(1,(TEXT("MAIN: fin de DEBUG\n"))); return 0; }
jc/md/lp-01/06Kernel Tracker8 DEBUG Thread_A (1) DWORD WINAPI A_MAIN(LPVOID p) { //p est un pointeur sur le handle du thread FIN DWORD dwExitCode,i,j=0; //Récupération des handles des événements A et B HANDLE hEVENT_A=OpenEvent( EVENT_ALL_ACCESS,FALSE,L"EVENT_A"); HANDLE hEVENT_B=OpenEvent( EVENT_ALL_ACCESS,FALSE,L"EVENT_B");
jc/md/lp-01/06Kernel Tracker9 DEBUG Thread_A (2) while(GetExitCodeThread(*(PHANDLE)p,&dwExitCode), dwExitCode == STILL_ACTIVE) { WaitForSingleObject(hEVENT_A,INFINITE);//attente… RETAILMSG(1,(TEXT("A_MAIN: j= %d\n"),++j)); for(i=0;i< ;i++) //histoire de passer le temps… ; //sans sortir du thread ResetEvent(hEVENT_A); //réinitialisation de…A SetEvent(hEVENT_B); //Déclenchement de…B } return 'A'; }
jc/md/lp-01/06Kernel Tracker10 DEBUG Thread_B (1) DWORD WINAPI B_MAIN(LPVOID p) { //p est un pointeur sur le handle du thread FIN DWORD dwExitCode,i,j=0; //Récupération des handles des événements A et B HANDLE hEVENT_A=OpenEvent( EVENT_ALL_ACCESS,FALSE,L"EVENT_A"); HANDLE hEVENT_B=OpenEvent( EVENT_ALL_ACCESS,FALSE,L"EVENT_B");
jc/md/lp-01/06Kernel Tracker11 DEBUG Thread_B (2) while(GetExitCodeThread(*(PHANDLE)p,&dwExitCode), dwExitCode == STILL_ACTIVE) { WaitForSingleObject(hEVENT_B,INFINITE); RETAILMSG(1,(TEXT("B_MAIN: j= %d\n"),++j)); ResetEvent(hEVENT_B); //réinitialisation de B… for(i=0;i< ;i++) //histoire de passer le temps... ; //sans sortir du thread SetEvent(hEVENT_A); //Déclenchement de A } return 'B'; }
jc/md/lp-01/06Kernel Tracker12 DEBUG Thread_FIN DWORD WINAPI FIN(LPVOID p) { //p pointeur sur le handle de lévénement fin MessageBox(NULL,_T("OK pour terminer"), _T("DEBUG"),MB_OK); return (DWORD)SetEvent(*(PHANDLE)p); }
jc/md/lp-01/06Kernel Tracker13 Exécution de DEBUG Générer DEBUG Télécharger limage (version Debug) Exécuter DEBUG pour vérifier son bon fonctionnement Fermer lapplication Fermer la fenêtre cible Nous allons étudier cette application avec loutil « Remote Kernel Tracker » proposé avec Platform Builder
jc/md/lp-01/06Kernel Tracker14 Options de Build version Debug
jc/md/lp-01/06Kernel Tracker15 Variante Sous « Kernel Tracker » beaucoup dévénements dus à lexistence des messages seront créés par le système. La suppression des messages « RETAIL » dans les threads A ou B, et le remplacement de la boîte de dialogue par une boucle vide dans le thread FIN simplifient les diagrammes observés, mais cela masque les interactions du programme avec le système et avec « Kernel Tracker » lui-même.
jc/md/lp-01/06Kernel Tracker16 Outils de Platform Builder Platform Builder propose un ensemble doutils spécialisés et un générateur de macro pour aider à la mise au point dapplications, vérifier le bon fonctionnement temporel, étudier les performances, visualiser les fenêtres, etc. Parmi ces outils, le « Remote Kernel Tracker » permet de visualiser graphiquement la chronologie dune application : création des process, threads, événements, enchaînement des événements, mutex, etc.
jc/md/lp-01/06Kernel Tracker17 Découverte de Kernel Tracker Téléchargement du noyau Lancement de Remote Kernel Tracker Lancement de DEBUG Collecte des données –Attente de quelques secondes –Fin de DEBUG après click sur OK –Fin de la collecte après quelques secondes –Déconnexion de la cible Analyse des données
jc/md/lp-01/06Kernel Tracker18 Démarrage de Remote Kernel Tracker
jc/md/lp-01/06Kernel Tracker19 Accepter le choix par défaut : OK
jc/md/lp-01/06Kernel Tracker20 Début de Remote Kernel Tracker
jc/md/lp-01/06Kernel Tracker21 Après démarrage de DEBUG
jc/md/lp-01/06Kernel Tracker22 À la fin de DEBUG
jc/md/lp-01/06Kernel Tracker23 Suppression de Auto-Follow Mode
jc/md/lp-01/06Kernel Tracker24 Déconnexion de la cible
jc/md/lp-01/06Kernel Tracker25 Analyse des données Récupération des valeurs des handles dans DEBUG pour identifier les traces Étude de diverses phases –Début de DEBUG –Lancement des threads A, B et FIN –Positionnement de lévénement A –Fonctionnement alternatif de A et B –Thread en attente –Fin de DEBUG Mesure des temps
jc/md/lp-01/06Kernel Tracker26 Récupération des handles
jc/md/lp-01/06Kernel Tracker27 Valeur des handles dans DEBUG ProcessID : 0x63D9CF8A ThreadID : 0x63D1013A hThread_A : 0x03D97A3A hThread_B : 0x03CECFA2 hThread_Fin : 0x03DB1512 hEvent_A : 0x03D979DA hEvent_B : 0x03DB1152 hEvent_Fin : 0x03DB140A
jc/md/lp-01/06Kernel Tracker28 Phase de démarrage de DEBUG FIN A B Prologue
jc/md/lp-01/06Kernel Tracker29 Positionnement du curseur Positionnement du curseur par un click gauche
jc/md/lp-01/06Kernel Tracker30 Positionnement du marqueur 1 Ouverture du menu par click droit
jc/md/lp-01/06Kernel Tracker31 Positionnement du marqueur 2 Marqueur 1 positionné Curseur déplacé
jc/md/lp-01/06Kernel Tracker32 Mesure du temps entre marqueurs Écart visualisé par une hachure Écart mesuré numériquement
jc/md/lp-01/06Kernel Tracker33 Action directe sur les marqueurs Dans ce cas le marqueur sera placé à lendroit du click droit Ouverture du menu par click droit dans la bande daffichage des temps
jc/md/lp-01/06Kernel Tracker34 Action directe sur les threads Ouverture du menu par click droit sur le nom du thread
jc/md/lp-01/06Kernel Tracker35 Fonctionnement des threads A et B B attend B reprend Déblocage de A A reprend A attend
jc/md/lp-01/06Kernel Tracker36 Détail de la mise en attente de B Déblocage de A SetEvent A Attente sur B WaitForSingleObject B
jc/md/lp-01/06Kernel Tracker37 Détail de la réactivation de A A reprend avec sa priorité normale (251) Inversion de priorité A est à la priorité 130 A revient à sa priorité normale (251) Le système a posé une section critique
jc/md/lp-01/06Kernel Tracker38 Détail de la mise en attente de A A dans sa boucle vide Blocage de A ResetEvent A Déblocage de B SetEvent B Attente de A WaitForSingleObject A
jc/md/lp-01/06Kernel Tracker39 Détail de la réactivation de B B reprend ResetEvent B B dans sa boucle vide
jc/md/lp-01/06Kernel Tracker40 Attente dans FIN de « OK » FIN est élu Le système ferme une section critique nécessaire pour gérer la boîte de dialogue B est élu Le système ouvre une section critique nécessaire pour gérer la boîte de dialogue
jc/md/lp-01/06Kernel Tracker41 Réception « OK » et fin du thread B Message « OK » arrivé Épilogue de B Suspension du thread B MAIN trouve B fini et entre dans le premier Sleep Fin du thread B
jc/md/lp-01/06Kernel Tracker42 Détail de la fin du thread B B dans la boucle vide SetEvent A Épilogue B trouve le thread FIN inactif et sort
jc/md/lp-01/06Kernel Tracker43 Fin du thread A Suspension du thread A Épilogue de A Fin du thread A
jc/md/lp-01/06Kernel Tracker44 Détail de la fin du thread A ResetEvent ASetEvent B A trouve le thread FIN inactif et sort Épilogue de A A dans la boucle vide
jc/md/lp-01/06Kernel Tracker45 Fermeture des événements CloseEvent A, CloseEvent B CloseEvent FIN Suppression de EVENT_FIN
jc/md/lp-01/06Kernel Tracker46 Fin du thread FIN Suspension du thread FIN Épilogue de DEBUG Fin de DEBUG
jc/md/lp-01/06Kernel Tracker47 Fin du process Épilogue du process Suspension de DEBUG Threads suspendus ou en sommeil
jc/md/lp-01/06Kernel Tracker48 Conclusion Nous avons exploré différents aspects Kernel Tracker –Visualisation de lenchaînement des taches –Mesure des temps –Utilisation en tant quanalyseur logique