1 / 35

Sistemsko programiranje

Sistemsko programiranje. VII. poglavlje Pouzdani modeli za rad s nitima. Ciljevi. Nakon svladavanja ovog poglavlja trebali bi znati : Riješavati još kompleksnije probleme s nitima Koristiti standardne modele za rad s nitima u dizajnu aplikacije Kreirati i koristiti timer-e za čekanje

suzuki
Download Presentation

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 VII. poglavlje Pouzdani modeli za rad s nitima

  2. Ciljevi Nakon svladavanja ovog poglavlja trebali bi znati: • Riješavati još kompleksnije probleme s nitima • Koristiti standardne modele za rad s nitima u dizajnu aplikacije • Kreirati i koristiti timer-e za čekanje • Praviti aplikacije koje su pouzdane i lake za održavanje • Razumjeti i izbjegavati mnoge uobičajene greške

  3. Dnevni red • 1. dio Višenitni modeli • 2. dio Model uvjetne varijable • 3. dio Vremensko čekanje • 4. dio Izbjegavanje pogrešnog koda - savjeti

  4. 1. dio Višenitni modeli

  5. Višenitni modeli • Prednosti korištenja modela za niti: • Brži dizajn i razvoj • Modeli su razumljivi i dobro iztestirani • Izbjegavju potencijalne probleme kod višenitnosti • Modeli pogađaju strukturu većine programskih problema • Vrlo jednostavni slučajevi, plus tri “klasična” modela • Gazda/šljaker • Tekuća vrpca (cjevovod, pipeline) • Klijent/Server • Osim toga i kombinirani modeli • Programiranje “u velikom”

  6. Datoteke Baze podataka Model Gazda/Šljaker Ulaz (Stream) Program Resursi Šljakeri Zadatak1 Gazda main () Zadatak2 ... ZadatakN Izračuni

  7. Model tekuće vrpce Poruka Log P1 C1 TO FROM DATA M1 M2 . . . M5 Q Q Q CN PN Predajnik Primatelj Q Proizvođači Potrošači

  8. Model Klijent/Server Server Nit 1 Stog 1 TLS Klijent 1 Kod Zajednički podaci Konstante Nit-Nit komunikacija i sinkronizacija Arg Nit 1 Specifični podaci TLS Nadgledanje statusa i upravljanje Server Nit N Stog 2 Stog TLS Klijent N Arg Arg Nit N Specifični podaci Statistike

  9. Kombinacije • Veliki sustavi su rijetko čisti primjerci jednog od modela • Faze u tekućoj vrpci često su implementirane kao gazda/šljaker sistemi • Server može posluživati zahtjeve klijenata po modelu tekuće vrpce • Uvijek koristiti dobre implementacije dokumentirajući pojedinačne module u terminima ovih modela • Lakše za održavanje, razumijevanje i otklanjanje grešaka

  10. 2. dio Model uvjetne varijable

  11. Model uvjetne varijable • Uvjetne varijable (conditional variable, CV) • Programiranje “u malom” • Koncepti preuzeti iz Pniti (POSIX niti, slijedi kasnije) • Nekoliko ključnih elemenata: • Struktura podataka tipa STATE_TYPE • Sadrži sve podatke kao što su poruke, sume za provjeru (checksums), itd. • Mutex i jedan ili više pridruženih događaja • Mutex štiti strukturu podataka • Događaji signaliziraju “bitne” promjene stanja strukture podataka • Boolove funkcijske izračune - “predikati uvjetne varijable” • Primjerice, “nova poruka je spremna” • Događaj je pridružen svakom predikatu slučajne varijable • Događaj se signalizira kada predikat uvjetne varijable postane istina

  12. Model uvjetne varijable: podaci Dijeljena struktura podataka: typedef struct _state_t { HANDLE Guard; /* Muteks koji štiti objekt */ HANDLE cvpSet; /* Auto-reset događaj */ . . . druge uvjetne varijable /* Struktura stanja s brojačima, itd. */ struct STATE_VAR_TYPE StateVar; } STATE_TYPE State; . . . /* Inicijaliziranje stanja, kreiranje muteksa i događaja */ . . .

  13. Model uvjetne varijable: proizvođač /* nit PROIZVOĐAČ koja modificira stanje */ WaitForSingleObject (State.Guard, INFINITE); /* Promjeni stanje tako da predikat CV vrijedi */ . . . State.StateVar.xyz = . . . ; SetEvent (State.cvpSet); ReleaseMutex (State.Guard); /* Kraj bitnog dijela kod proizvođača */ . . .

  14. Model uvjetne varijable: potrošač /* Nit POTROŠAČ čeka na određeno stanje */ WaitForSingleObject (State.Guard, INFINITE); while (!cvp(&State)) { ReleaseMutex (State.Guard); WaitForSingleObject (State.CvpSet, TimeOut); WaitForSingleObject (State.Guard, INFINITE); } . . . ReleaseMutex (State.Guard); /* Kraj bitnog dijela kod potrošača */

  15. Komentari modela uvjetne varijable • Moramo ponavljati petlju i testirati • Timeout je konačan – parametar za podešavanje izvedbe • Ovaj model izbjegava propuštene signale i druge probleme • Ovo je verzija koja “odašilje” (“broadcast”) • Više potrošača otpušta se s jednim proizvođačevim SetEvent() • Ponašanje u stvarnoj primjeni ovisi o cvp() i značenju proizvodnje/potrošnje • Koristi se auto-reset događaj i SetEvent() • “Signalna” verzija koristi manual-reset događaj i PulseEvent() • Samo jedan potrošač je otpušten

  16. SignalObjectAndWait (1/2) • Tri osnovna koraka petlje kod potrošača • Otključaj muteks • Čekaj na događaj • Zaključaj muteks ponovno • Prva dva nisu potpuno jednostavna • Proizvođač može signalizirati prije nego potrošač čeka • Rizik: propušteni signal – zbog toga imamo timeout (točno vrijeme čekanja) • SignalObjectAndWait() kombinira prva dva koraka • Jedna jednostavna funkcija • Pniti kombiniraju sva tri koraka • >= NT 4.0 (nema na Win 9x, Me)

  17. SignalObjectAndWait (2/2) DWORD SignalObjectAndWait( HANDLE hObjectToSignal, // Muteks HANDLE hObjectToWaitOn, // Događaj DWORD dwMilliseconds, // timeout u ms BOOL bAlertable )// Koristiti FALSE • SOAW je opće namjene • Ovdje pokazujemo samo upotrebu muteks-događaj • Timeout često puta može biti i beskonačan • Treba biti siguran da je: #define _WIN32_WINNT 0x400 // WINBASE.H

  18. Korištenje modela uvjetne varijable • Proizvođač zaključa muteks, promjeni stanje, postavi događaj i otključa muteks • Događaj se mora postaviti sa zaključanim muteksom • Potrošač testira predikat uvjetne varijable sa zaključanim muteksom • Ako predikat nije istina, potrošač mora otključati muteks prije čekanja na događaj • Čekanje na događaj mora imati timeout – da se izbjegne propušteni signal • Osima ako koristite SOAW! • Potrošač uvijek resetira predikat nakon čekanja na događaj • Potrošač je uvijek vlasnik muteksa kada izlazi iz petlje • i ako se tijelo petlje izvodi i ako ne

  19. Varijacije modela uvjetne varijable • Unutar proizvođač/potrošač koda, više niti je oslobođeno • Auto-reset događaj • SetEvent • Ili, možda postoji samo jedna poruka, a više niti potrošača • Događaj treba biti manual-reset • Proizvođač treba pozvati PulseEvent • Osigurati da se točno jedna nit oslobodi čekanja

  20. Ako smo zainteresirani za sljedeći događaj /* Nit POTROŠAČ čeka na SLJEDEĆU promjenu stanja */ WaitForSingleObject (State.Guard, INFINITE); do { SignalObjectAndWait (State.Guard, State.cvpSet, TimeOut, FALSE); WaitForSingleObject (State.Guard, INFINITE); } while (!cvp(&State)); /* Nit sada posjeduje muteks, a cvp(&State) je istinit */ /* Poduzmi odgovarajuću akciju, možda promjena stanja */ . . . ReleaseMutex (State.Guard); /* kraj bitnog dijela kod potrošača */

  21. 3. dio Vremensko čekanje

  22. Vremensko čekanje (1/2) • Tip objekata jezgre za čekanje >= Win2K • Za periodično izvođenje zadaća ili točno u određeno vrijeme • Kreiranje našeg vremenskog signala: • Kreira se vremenska nit • Nit postavlja događaj nakon “buđenja” iz funkcije Sleep • Dva tipa: • Vremenska sinkronizacija: Koristi funkciju koja završava – mora biti u stanju mogućeg uzbunjivanja (alertable) • Manual reset vremenska notifikacija: čeka na handle timer-a

  23. Vremensko čekanje (2/2) HANDLE CreateWaitableTimer( LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, // Manual reset state LPCTSTR lpTimerName // *timer object name ); • Timer je inicijalno neaktivan, ali se kasnije aktivira • Imenovan, zato postoji i funkcija OpenWaitableTimer

  24. Postavljanje timer-a za čekanje BOOL SetWaitableTimer( HANDLE hTimer, const LARGE_INTEGER *pDueTime, LONG lPeriod, // periodički interval PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, BOOL fResume /* zastavica za stanje ponovnog nastavljanja */ );

  25. Otkazivanje timer-a za čekanje CancelWaitableTimer otkazuje zadnji pozvani SetWaitableTimer • Neće promjeniti signalizirano stanje timer-a • Koristiti drugi put SetWaitableTimer ako to želimo BOOL CancelWaitableTimer( HANDLE hTimer );

  26. Funkcija za čekanje s mogućnosti uzbunjivanja (alertable) • Opcija kod više funkcija za čekanje – Najčešće “Ex” verzije DWORD SleepEx( DWORD dwMilliseconds, BOOL bAlertable ); • Vraća čim se: • završi vrijeme čekanja • ako je bAlerable postavljen, i izvršen je poziv primjerice WaitForSingleObjectEx ( …, BOOL bAlertable); WaitForMultipleObjectsEx (…, BOOL bAlertable);

  27. 4. dio Izbjegavanje pogrešnog koda - savjeti

  28. Izbjegavanje pogrešnog koda - savjeti (1/3) • Obratiti pažnju na dizajn, implementaciju i korištenje poznatih programskih modela • Najbolja tehnika za ‘debagiranje’ : otpočetka ne kreirati bagove • Mnogi ozbiljni defekti će prouzrokovati najšire i najskuplje testiranje • Debagiranje mijenja vremensko ponašanje • Tako se maskiraju “uvjeti utrke” koji mi želimo postići, tj. ne vidimo ono što želimo vidjeti

  29. Izbjegavanje pogrešnog koda - savjeti (2/3) • Izbjegavati oslanjanje na unutarnju strukturu niti • Nikada se ne treba kladiti “koja će nit prije” • Zakazivanje za izvršenje (Scheduling) nije isto što i sinkronizacija • Mogu se pojaviti višestruke “utrke” za podacima • I onda kada koristimo muteksa za zaštitu zajedničkih podataka • Izbjegavati totalne zastoje misleći kakvo će biti zajedničko funkcioniranje • Nikada ne dijeliti događaje između predikata

  30. Izbjegavanje pogrešnog koda - savjeti (3/3) • Oprez kod dijeljenja stogova i s time vezane korupcije memorijskog prostora • Oprez: nema upozorenja kada se stog niti prepuni • Treba koristiti volatile modifikator spremanja varijabli • Koristiti model uvjetnih varijabli kako treba • Razumjeti invarijante i predikate uvjetne varijable • Neka bude što jednostavnije • Testirati na više sistema (jedno- i više-procesorskim) • Testiranje je neophodno ali ne i dovoljno • Treba biti spreman na neugodna iznenađenja

  31. Primjedbe oko blokiranja niti • U bilo kojem trenutku nit može otići u stanje “spavanja” na neograničen vremenski period • Ne postoji uređenje između niti, osim ako ga mi ne uvedemo • Zakazivanje niti za izvršavanje može biti jako različito • Različite izvedbe operacijskih sustava • Različiti modeli istog sustava • Sustavi s različitim brzinama procesora • Eksplicitno sinkroniziranje je uvijek potrebno • Nema vremena čekanja (timeout) kod poziva pthread_join()

  32. Cijepanje riječi (1/2) • Jedan muteks treba koristiti u svakom kritičnom odsječku povezanim s dijeljenim resursom • poznato i kao “borba oko cache linije” - SMP • Primjer: procesor može pristupiti četveroriječnoj memorijskoj jedinici • 64 bita, jer je riječ 16 bitna • 16-bitne riječi nisu odvojeni resursi • kad različite niti pristupaju različitim vrijednostima koje leže u istim četveroriječnim jedinicama memorije, tada imamo cijepanje, tj. borbu za riječ • Cijela četvero-riječ treba biti zaštičena s jednim muteksom

  33. 11 11 11 11 11 51 22 22 22 22 22 22 33 33 33 33 33 33 44 44 48 44 44 48 Cijepanje riječi (2/2) Memorija 4 16- Bitne riječi Nit A Nit B Čita Čita Piše u prvi bajt Piše na zadnji bajt Završava Završava Vrijednost Niti B pobjeđuje; Idući puta Nit A može pobjediti

  34. Izbjegavanje totalnog zastoja, hijerarhija zaključavanja • Izbjegavati totalni zastoj koristeći hijerarhiju zaključavanja gdje ćemo mutekse uvijek zaključavati po istom redoslijedu • Otključavati treba u obrnutom redosljedu • Dodatne primjedbe kod totalnog zastoja • Tijekom razvoja i otklanjana grešaka • Osigurati da je višestruko zaključavanje uvijek u istom redoslijedu • Dokumentirati hijerarhiju zaključavanja • Hijerahija zaključavanja je dokazano bez totalnog zastoja

  35. Nema totalnog zastoja s hijerahijskim zaključavanjem AddSharedElement Nit DeleteSharedElement Nit OS SCHEDULER Izvodi se Spremna Lock (&ListA.guard) Run Prebaci izvođenje Running Spremna Blokiranje Lock (&ListA.guard) Run Lock (&ListB.guard) Izvodi se Blokirana Unock (&ListB.guard) Unlock (&ListA.guard) Deblokiranje Spremna Run Prebaci izvođenje Lock (&ListB.guard) Spremna Izvodi se Unock (&ListB.guard) Unlock (&ListA.guard)

More Related