1 / 56

Sistemsko programiranje

Sistemsko programiranje. V. poglavlje Upravljanje nitima. Ciljevi. Nakon svladavanja ovog poglavlja trebali bi znati : Opisati upravljanje Windows nitima Koristiti niti u Windows aplikacijama Koristiti niti pomoću funkcija iz C biblioteke Praviti i izvršavati aplikacije s nitima

tawana
Télécharger la présentation

Sistemsko programiranje

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Sistemsko programiranje V. poglavlje Upravljanje nitima

  2. Ciljevi Nakon svladavanja ovog poglavlja trebali bi znati: • Opisati upravljanje Windows nitima • Koristiti niti u Windows aplikacijama • Koristiti niti pomoću funkcija iz C biblioteke • Praviti i izvršavati aplikacije s nitima • Opisati raspodjelu poslova i sustave s više procesora

  3. Niti: Dobre i loše strane • Dobre strane • Jednostavniji programski modeli • Brži izvršavanje koda – u većini slučajeva • Iskorištavanje više procesora • Iskorištavanje ugrađenog paralelizma u samoj aplikaciji • Kod je pouzdan, razumljiv i lak za održavanje • Loše strane • Lošija izvedba nego sekvencijalna – u nekim slučajevima • Mogućnost defekta (izvođenja koda na način koji ne želimo)

  4. Dnevni red • 1. Pregled procesa i niti • 2. Upravljanje nitima • 3. Čekanje da nit završi • 4. C biblioteka i niti • 5. Demonstracija: Izgradnja aplikacije s nitima • 6. Prioritet niti, raspodjela, višeprocesorski sustavi

  5. 1. dio Pregled procesa i niti

  6. Pregled procesa i niti (1/2) • Niti unutar procesa dijele podatke i kod • Svaka nit ima svoj vlastiti stog za pozive funkcija • Pozivajuća nit može prosljediti parametar novoj niti u trentuku kreiranja • Taj parametar je na stogu • Svaka nit može zauzeti svoj vlasiti memorijski spremnik (Thread Local Storage - TLS) i postavljati TLS vrijednosti

  7. Pregled procesa i niti (2/2) • Zakazani trenutak izvođenja niti (scheduling) je neovisan, te samo izvođenje niti je neovisno • Izvršioc zakazuje, tj. raspodjeljuje kako će se i kada niti izvoditi • Niti se izvode asinkrono • Može se zaustaviti (pauzirati) izvođenje niti • Ili ponovno restartati u bilo kojem trenutku

  8. Proces i njegove niti Process Kod Globalne varijable Procesni heap Resursi procesa Otvorene datoetke, Heapovi, · · · Blok okruženja (environment) Nit 1 Nit N TLS TLS · · · Stog Stog

  9. Niti koje izvode paralelne zadatke Program s jednom niti Višenitni program Nit 1 Nit 2 Pročitaj datoeku A Pročitaj datoteku A Pročitaj datoteku B Pročitaj datoteku B Čekaj da nit 1 i nit 2 završe Nit 3 Spoji podatke iz obje datoteke Spoji podatke iz obje datoteke Nit 3 Čitanje datoteke B prije datoteke A bi dalo jednak rezultat

  10. 2. dio Upravljanje nitima

  11. Upravljanje nitima • Kreiranje niti • Funkcija koja je ulazna točka u nit • Završavanje niti • Izlazni kodovi niti • Identitet niti • Privremeno zaustavljanje i nastavljanje izvršavanja niti

  12. Kreiranje niti (1/6) • Odrediti početnu adresu niti unutar koda procesa • Odrediti veličinu stoga, a stog će zauzeti mjesto unutar adresnog prostora procesa • Stog se ne može naknadno proširiti

  13. Kreiranje niti (2/6) • Odrediti pokazivač na parametar za nit • Može biti pokazivač na bilo koji tip • Interpretira se od strane same niti • CreateThread vraća kao rezultat i ID od niti i njen handle • Vrijednost NULL od handle-a govori da je došlo do greške

  14. Kreiranje niti (3/6) HANDLE CreateThread ( LPSECURITY_ATTRIBUTES lpsa, DWORD cbStack, LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpvThreadParm, DWORD dwCreate, LPDWORD lpIDThread )

  15. Kreiranje niti (4/6) • Parametri lpsa • Struktura sa sigurnosnim atributima (koristiti NULL) cbStack • Veličina u byte-ovima za stog novokreirane niti • Staviti 0 za preddefiniranu vrijednost primarne niti (od 1MB)

  16. Kreiranje niti (5/6) lpStartAddr • Pokazivač na adresu funkcije (unutar pozivajućeg procesa) koja se izvršava • Ta funkcija prihvaća jedan pokazivač kao parametar i vraća 32-bitni DWORD izlazni kod niti • Nit može interpretirati argument kao DWORD ili kao pokazivač lpThreadParm • pokazivač koji se prenosi kao parametar u nit

  17. Kreiranje niti (6/6) dwCreate • Ako je 0, nit se automatski izvršava • Ako je CREATE_SUSPENDED, nova nit će biti u stanju suspenzije, te će se moći nastaviti izvršavati tek nakon poziva ResumeThread funkcije lpIDThread • Pokazivač na DWORD koji prima ID koji je pridjeljen to j niti; NULL smijemo staviti na W2000/NT

  18. Funkcija koja je ulazna točka u nit Ovako mora izgledati funkcija koja se izvodi prilikom startanja određene niti: DWORD WINAPI MyThreadFunc ( PVOID pThParam ) { . . . ExitThread (ExitCode); /* OR */ return ExitCode; }

  19. Završavanje niti (1/3) • Sve niti se završavaju s pozivom ExitProcess • Proces i sve njegove niti završavaju s izvođenjem • Izlazni kod koji je vraćen od primarne niti procesa je isti kao izlazni kod cijelog procesa • Ili nit može jednostavno završiti i vratiti svoj izlazni kod

  20. Završavanje niti (2/3) • ExitThread je preferirana tehnika • Prilikom izlaska oslobađa se prostor zauzet za stog VOID ExitThread (DWORD dwExitCode) • Kada završi zadnja nit u procesu, tada završava i sam proces.

  21. Završavanje niti (3/3) • Može se završiti drugu nit iz tekuće niti pozivom TerminateThread • Opasno: Neće se osloboditi memorijski prostor stoga niti i drugih resursa • Bolje je ostaviti da nit sama završi (ako se može) • Nit će ostati u sistemu sve dok se zadnji handle unutar nje ne zatvori (koristeći CloseHandle) • Nakon toga nit će biti obrisana • Sve ostale niti mogu dobiti izlazni kod niti koja je završila

  22. Izlazni kodovi niti BOOL GetExitCodeThread ( HANDLE hThread, LPDWORD lpdwExitCode ) lpdwExitCode • Sadrži izlazni kod niti • Može poprimiti vrijednost STILL_ACTIVE

  23. Identitet niti (1/2) • Nit ima stalni “ThreadId” (za cijelo vrijeme svog “života”) • Niti se obično pristupa preko njenog HANDLE-a • ID se može pretvoriti u HANDLE

  24. Identitet niti (2/2) HANDLE GetCurrentThread (VOID); DWORD GetCurrentThreadId (VOID); HANDLE OpenThread ( DWORD dwDesiredAccess, BOOL InheritableHandle, DWORD ThreadId ); /* >= verzije Windows 2000*/

  25. Privremeno zaustavljanje i nastavljanje izvođenja niti (1/2) • Svaka nit ima brojač koji određuje njenu suspenziju • Nit se može izvoditi samo ako je taj brojač jednak 0 • Nit se može kreirati odmahu stanju suspenzije • Nit može uvećavati ili umanjivati brojač suspenzije od druge niti: DWORD ResumeThread (HANDLE hThread)

  26. Privremeno zaustavljanje i nastavljanje izvođenja niti (2/2) DWORD SuspendThread (HANDLE hThread) • Obje funkcije vraćaju prethodno stanje brojača suspenzije • 0xFFFFFFFF ukazuje na pogrešku • Korisno ako želimo postići istovremeni start svih niti • Ne dopuštamo da se niti startaju dok ne kompletiramo inicijalizaciju • Upotreba nesigurna za opću sinkroniczaciju

  27. 3. dio Čekanje da nit završi

  28. Čekanje da nit završi (1/2) Čekanje na niti se obavlja tako da se koriste funkcije za čekanje opće namjene WaitForSingleObjectili WaitForMultipleObjects • Koriste se handle-ovi od niti Funkcije za čekanje čekaju da se to signalizira preko handle-a od niti • handle od niti je signaliziran kada nit završi s radom

  29. Čekanje da nit završi (2/2) • ExitThread i TerminateThread postavljaju objekte u signalizirano stanje • Oslobađajući sve druge niti koje čekaju na taj objekt • ExitProcess stavlja proces i sve njegove niti u signalizirano stanje

  30. Funkcije za čekanje (1/2) DWORD WaitForSingleObject ( HANDLE hObject, DWORD dwTimeOut )

  31. Funkcije za čekanje (2/2) DWORD WaitForMultipleObjects ( DWORD cObjects, LPHANDLE lphObjects, BOOL fWaitAll, DWORD dwTimeOut ) Vraća: Razlog završetka čekanja

  32. Opcije čekanja (1/2) Određuje se ili jedan handle hObject Ili cijeli niz cObjects s početnom adresom lphObjects cObjects ne smije premašiti vrijednost MAXIMUM_WAIT_OBJECTS - 64

  33. Opcije čekanja (2/2) • dwTimeOut je u milisekundama • 0 znači da funkcija trenutno završava i samo testira stanje navedenih objekata (ili samo jednog objekta) • Koristi se INFINITE ako nema vremena čekanja • Čekaj zauvijek da neka nit završi • GetExitCodeThread • Vraća izlazni kod niti

  34. Vrijednosti koje vraća funkcija čekanja (1/3) fWaitAll • Ako je TRUE, čeka se na završetak svih niti Moguće vrijednosti koje se vraćaju: • WAIT_OBJECT_0 • Nit je završena (ako pozivamoWaitForMultipleObjects;fWaitAll postavljena)

  35. Vrijednosti koje vraća funkcija čekanja (2/3) • WAIT_OBJECT_0 + n gdje je 0 <= n < cObjects • Ako oduzmemo WAIT_OBJECT_0 od vraćene vrijednosti, onda možemo točno odrediti koja je nit završila pri pozivuWaitForMultipleObjects s postavljenim fWaitAll na FALSE • WAIT_TIMEOUT • Vrijeme čekanja je isteklo

  36. Vrijednosti koje vraća funkcija čekanja (3/3) • WAIT_ABANDONED • Nije moguće čekanje sa zadanim handle-ovima niti • WAIT_FAILED • Treba pozvatiGetLastError za specifični kod greške za niti

  37. 4. dio C biblioteka i niti

  38. C biblioteka i niti Skoro svi programi (i funkcije za niti) koriste C biblioteku Ali obična C biblioteka nema neke sigurnosne stavke, tj. nije “thread safe” C funkcija _beginthreadex ima potpuno jednake parametre kao CreateThread

  39. Korištenje _beginthreadex (1/3) Potrebno je vršiti kastanje (cast) izlazne vrijednosti od _beginthreadex na tip(HANDLE) Koristiti _endthreadex namjesto ExitThread #include <process.h>

  40. Korištenje _beginthreadex (2/3) Treba postaviti višenitno okruženje kako slijedi: • #define _MT u svakoj datoteci izvornog koda prije uključivanja <windows.h> • Povezivanje treba vršiti s bibliotekom LIBCMT.LIB • Preddefiniranu biblioteku LIBC.LIB treba zamjeniti s ovom

  41. Korištenje _beginthreadex (3/3) Preferirana metoda ako koristimo Visual C++ Iz menija: • Build Settings — C/C++ Tab • Code Generation category • Odabrati multithreaded run-time library

  42. Primjer: Jednostavna nit “gazda” HANDLE hWork[K]; volatile LONGLONG WorkDone[K], iTh; /* K handle-ova za K šljakera svi šljakeri rade isti posao */ . . . for (iTh = 0; iTh < K; iTh++) { WorkDone[ith] = 0; hWork[iTh] = _beginthreadex (NULL, 0, WorkTh, (PVOID)&iTh, 0, NULL); } WaitForMultipleObjects (K, hWork, TRUE, INFINITE); for (iTh = 0; iTh < K; iTh++) printf (“Thread %d did %d workunits\n”, iTh, WorkDone[iTh]);

  43. Primjer: Jednostavna nit “šljaker” DWORD WINAPI WorkTh (PVOID pThNum) { DWORD ThNum = (DWORD)(*pThNum); while (. . .) { /* šljakaj */ WorkDone[ThNum]++; } _endthreadex (0); }

  44. 5. dio Demonstracija: Izgradnja aplikacije s nitima - pomoću npr. VC 6.0

  45. Demonstracija (1/3) Implementaciaj višenitnog programa za brojanje riječi wcMT • Uključiti izvorni kod programa za brojanje riječi wc i izvršavati ga kao nit • Kreirati po jednu nit za svaku datoteku koju treba analizirati • Usporediti izvedbu kada se izvršava kao jedan proces, kao višeprocesna i kao višenitna implementacija • Ako se koriste C biblioteka, napraviti odna “thread-safe” verziju! (znači koristiti CreateThread i pripadajuće funkcije)

  46. Demonstracija (2/2) OVO JE “GAZDA”/”ŠLJAKER” PRINCIP • To je uobičajena tehnika upravljanja nitima Program Resursi Šljakeri Nit 0 Gazda Datoteke main () Nit 1 Nit K-1

  47. 6. dio Prioritet niti, raspodjela, višeprocesorski sustavi

  48. Prioritet niti i zakazivanje izvršenja Windows jezgra izvodi nit s najvišim prioritetom koja je spremna za izvršenje 4 klase prioriteta se postavljaju s CreateProcess • IDLE_PRIORITY_CLASS (osnovni prioritet 4) • NORMAL_PRIORITY_CLASS (9 ili 7) • HIGH_PRIORITY_CLASS (13) • REALTIME_PRIORITY_CLASS (24) Windows XP proširenja

  49. Prioritet niti (1/2) Mjenjanje ili određivanje prioriteta niti • Za sebe (tekuću nit) • Za drugi proces, ako smijemo, tj. određuju atributi sigurnosti DWORD SetPriorityClass ( HANDLE hProcess, DWORD dwPriority) DWORD GetPriorityClass ( HANDLE hProcess)

  50. Prioritet niti (2/2) Prioriteti niti se postavljaju relativno na osnovni prioritet • THREAD_PRIORITY_LOWEST • THREAD_PRIORITY_BELOW_NORMAL • THREAD_PRIORITY_NORMAL • THREAD_PRIORITY_ABOVE_NORMAL • THREAD_PRIORITY_HIGHEST

More Related