This shows you the differences between two versions of the page.
so:laboratoare-2013:resurse:threaduri_extra [2014/03/05 22:19] 127.0.0.1 external edit |
so:laboratoare-2013:resurse:threaduri_extra [2017/04/11 10:48] (current) adrian.stanciu [Modificarea dimensiunii și adresei de start a stivei] |
||
---|---|---|---|
Line 5: | Line 5: | ||
===== Terminarea thread-urilor ===== | ===== Terminarea thread-urilor ===== | ||
- | Există și posibilitatea ca un fir de execuţie să termine un alt fir, folosind mecanismul de "__thread cancellation__". Pentru a face acest lucru se folosește funcţia ''pthread_cancel'' care primește ca parametru id-ul firului de execuţie ce urmează să fie terminat : | + | Există și posibilitatea ca un fir de execuţie să termine un alt fir, folosind mecanismul de "__thread cancellation__". Pentru a face acest lucru se folosește funcţia ''pthread_cancel'' care primește ca parametru id-ul firului de execuţie ce urmează să fie terminat: |
<code c>int pthread_cancel(pthread_t thread);</code> | <code c>int pthread_cancel(pthread_t thread);</code> | ||
Line 11: | Line 11: | ||
Un thread unificabil care a fost terminat în acest mod trebuie așteptat folosind ''pthread_join'' pentru ca resursele folosite de el să fie eliberate. Un fir terminat cu ''pthread_cancel'' va întoarce valoarea PTHREAD_CANCELED. | Un thread unificabil care a fost terminat în acest mod trebuie așteptat folosind ''pthread_join'' pentru ca resursele folosite de el să fie eliberate. Un fir terminat cu ''pthread_cancel'' va întoarce valoarea PTHREAD_CANCELED. | ||
Totuși trebuie avut grijă la folosirea acestui mecanism, întrucât un thread este posibil să fie terminat înainte de a avea posibilitatea să elibereze anumite resurse folosite. Din aceasta cauză un thread poate să controleze dacă și când poate fi terminat de către un alt thread. | Totuși trebuie avut grijă la folosirea acestui mecanism, întrucât un thread este posibil să fie terminat înainte de a avea posibilitatea să elibereze anumite resurse folosite. Din aceasta cauză un thread poate să controleze dacă și când poate fi terminat de către un alt thread. | ||
- | Din punctul de vedere al posibilităţii terminării folosind ''pthread_cancel'' un thread poate fi : | + | Din punctul de vedere al posibilităţii terminării folosind ''pthread_cancel'' un thread poate fi: |
*cancelabil asincron - un astfel de fir poate fi terminat de către un alt fir în orice punct al execuţiei. | *cancelabil asincron - un astfel de fir poate fi terminat de către un alt fir în orice punct al execuţiei. | ||
*cancelabil sincron - un astfel de fir NU poate fi terminat în orice punct al execuţiei sale, ci numai în anumite puncte specifice. | *cancelabil sincron - un astfel de fir NU poate fi terminat în orice punct al execuţiei sale, ci numai în anumite puncte specifice. | ||
*necancelabil - un astfel de fir nu poate fi terminat folosind ''pthread_cancel''. | *necancelabil - un astfel de fir nu poate fi terminat folosind ''pthread_cancel''. | ||
- | Stabilirea tipului unui fir de execuţie din acest punct de vedere se face folosind funcţiile : | + | Stabilirea tipului unui fir de execuţie din acest punct de vedere se face folosind funcţiile: |
<code c> | <code c> | ||
Line 27: | Line 27: | ||
Folosind ''pthread_setcancelstate'' pot fi implementate regiuni critice, în sensul că tot codul dintr-o astfel de regiune trebuie executat în întregime sau deloc, practic firul să nu poată fi terminat de către un alt fir în timp ce se găsește într-o astfel de regiune. | Folosind ''pthread_setcancelstate'' pot fi implementate regiuni critice, în sensul că tot codul dintr-o astfel de regiune trebuie executat în întregime sau deloc, practic firul să nu poată fi terminat de către un alt fir în timp ce se găsește într-o astfel de regiune. | ||
- | Funcţia ''pthread_setcanceltype'' poate fi folosită pentru a schimba tipul de răspuns la o cerere de terminare : asincron sau sincron. Argumentul ''type'' indică noul tip și poate fi ''PTHREAD_CANCEL_ASYNCHRONOUS'' (pentru ca firul să poată fi terminat asincron, deci oricând) sau ''PTHREAD_CANCEL_DEFERRED'' (pentru ca o cerere de terminare sa fie amânată până când se ajunge într-un punct în care este posibilă terminarea firului). La fel, în ''oldtype'', dacă nu este NULL se poate obţine starea anterioară. | + | Funcţia ''pthread_setcanceltype'' poate fi folosită pentru a schimba tipul de răspuns la o cerere de terminare: asincron sau sincron. Argumentul ''type'' indică noul tip și poate fi ''PTHREAD_CANCEL_ASYNCHRONOUS'' (pentru ca firul să poată fi terminat asincron, deci oricând) sau ''PTHREAD_CANCEL_DEFERRED'' (pentru ca o cerere de terminare sa fie amânată până când se ajunge într-un punct în care este posibilă terminarea firului). La fel, în ''oldtype'', dacă nu este NULL se poate obţine starea anterioară. |
În mod implicit la crearea unui fir folosind ''pthread_create'' starea lui este caracterizată de ''PTHREAD_CANCEL_ENABLE'' și ''PTHREAD_CANCEL_DEFERRED''. | În mod implicit la crearea unui fir folosind ''pthread_create'' starea lui este caracterizată de ''PTHREAD_CANCEL_ENABLE'' și ''PTHREAD_CANCEL_DEFERRED''. | ||
Line 33: | Line 33: | ||
Funcţiile ''pthread_create'', ''pthread_setcancelstate'' și ''pthread_setcanceltype'' întorc 0 în caz de succes și un cod de eroare nenul în caz de eșec. | Funcţiile ''pthread_create'', ''pthread_setcancelstate'' și ''pthread_setcanceltype'' întorc 0 în caz de succes și un cod de eroare nenul în caz de eșec. | ||
- | În cazul în care un fir este cancelabil sincron, așa cum a fost precizat, terminarea lui se poate face numai în anumite puncte ale execuţiei sale. Practic cererile de terminare sunt amânate până se ajunge într-un astfel de punct, numit și ''cancellation point''. Când se ajunge într-un astfel de punct se testează dacă există cereri de terminare, și dacă da, firul este terminat. Cel mai direct mod de a crea un astfel de punct este apelând funcţia : | + | În cazul în care un fir este cancelabil sincron, așa cum a fost precizat, terminarea lui se poate face numai în anumite puncte ale execuţiei sale. Practic cererile de terminare sunt amânate până se ajunge într-un astfel de punct, numit și ''cancellation point''. Când se ajunge într-un astfel de punct se testează dacă există cereri de terminare, și dacă da, firul este terminat. Cel mai direct mod de a crea un astfel de punct este apelând funcţia: |
<code c> | <code c> | ||
Line 41: | Line 41: | ||
Dacă într-un program se folosește acest mecanism de terminare a firelor folosind ''pthread_cancel'', această funcţie ar trebui apelată periodic în cadrul unei funcţii asociate unui thread în care se fac multe procesări, în punctele în care firul poate fi terminat fără a rămâne resurse neeliberate și fără a produce alte efecte nedorite. | Dacă într-un program se folosește acest mecanism de terminare a firelor folosind ''pthread_cancel'', această funcţie ar trebui apelată periodic în cadrul unei funcţii asociate unui thread în care se fac multe procesări, în punctele în care firul poate fi terminat fără a rămâne resurse neeliberate și fără a produce alte efecte nedorite. | ||
- | Pe lângă ''pthread_testcancel'' mai există o serie de alte funcţii al căror apel reprezintă un punct de cancelare. Aceste funcţii sunt următoarele : | + | Pe lângă ''pthread_testcancel'' mai există o serie de alte funcţii al căror apel reprezintă un punct de cancelare. Aceste funcţii sunt următoarele: |
*''pthread_join'' | *''pthread_join'' | ||
*''pthread_cond_wait'' | *''pthread_cond_wait'' | ||
Line 56: | Line 56: | ||
Atributele unui fir de execuţie (cu o excepţie) sunt specificate la crearea firului de execuţie și __nu pot fi schimbate__ pe perioada în care firul de execuţie este folosit. | Atributele unui fir de execuţie (cu o excepţie) sunt specificate la crearea firului de execuţie și __nu pot fi schimbate__ pe perioada în care firul de execuţie este folosit. | ||
- | Pentru __iniţializarea__ și respectiv __distrugerea__ unui obiect ce reprezintă atributele unui fir de execuţie avem la dispoziţie funcţiile : | + | Pentru __iniţializarea__ și respectiv __distrugerea__ unui obiect ce reprezintă atributele unui fir de execuţie avem la dispoziţie funcţiile: |
<code c> | <code c> | ||
Line 63: | Line 63: | ||
</code> | </code> | ||
- | Pentru a stabili anumite atribute specifice ale unui fir, trebuie urmaţi câţiva pași : | + | Pentru a stabili anumite atribute specifice ale unui fir, trebuie urmaţi câţiva pași: |
- | # se creează un obiect de tipul ''pthread_attr_t'', de exemplu declarând o variabilă de acest tip. | + | * se creează un obiect de tipul ''pthread_attr_t'', de exemplu declarând o variabilă de acest tip. |
- | # se apelează funcţia ''pthread_attr_init'' căreia i se dă ca parametru un pointer la acest obiect. Această funcţie iniţializează atributele cu valorile lor implicite. | + | * se apelează funcţia ''pthread_attr_init'' căreia i se dă ca parametru un pointer la acest obiect. Această funcţie iniţializează atributele cu valorile lor implicite. |
- | # se modifică obiectul ce contine atributele folosind una din funcţiile prezentate mai jos, pentru ca să se obţină atributele dorite. | + | * se modifică obiectul ce contine atributele folosind una din funcţiile prezentate mai jos, pentru ca să se obţină atributele dorite. |
- | # se transmite un pointer la aceste atribute funcţiei ''pthread_create''. | + | * se transmite un pointer la aceste atribute funcţiei ''pthread_create''. |
- | # se apelează funcţia ''pthread_attr_destroy'' pentru a elibera obiectul ce reprezintă atributele (variabila de tip ''pthread_attr_t'' nu este însă dezalocată, ea poate fi refolosită utilizând ''pthread_attr_init''). | + | * se apelează funcţia ''pthread_attr_destroy'' pentru a elibera obiectul ce reprezintă atributele (variabila de tip ''pthread_attr_t'' nu este însă dezalocată, ea poate fi refolosită utilizând ''pthread_attr_init''). |
Un același obiect de tip ''pthread_attr_t'' poate fi folosit pentru crearea mai multor fire de execuţie distincte și nu este necesar să fie păstrat după crearea acestora. | Un același obiect de tip ''pthread_attr_t'' poate fi folosit pentru crearea mai multor fire de execuţie distincte și nu este necesar să fie păstrat după crearea acestora. | ||
Line 77: | Line 77: | ||
==== Modificarea atributului detașabil/unificabil ==== | ==== Modificarea atributului detașabil/unificabil ==== | ||
- | Pentru a seta/verifica tipul unui fir de execuţie din punct de vedere detașabil/unificabil se pot utiliza următoarele funcţii : | + | Pentru a seta/verifica tipul unui fir de execuţie din punct de vedere detașabil/unificabil se pot utiliza următoarele funcţii: |
<code c> | <code c> | ||
Line 86: | Line 86: | ||
Primul parametru este un pointer la obiectul reprezentând atributele, iar al doilea parametru reprezintă starea dorită - unificabil/detașabil. Deoarece implicit sunt create fire unificabile (valoarea ''PTHREAD_CREATE_JOINABLE''), această funcţie trebuie apelată doar dacă se creează fire detașabile și în acest caz al doilea parametru trebuie să aibă valoarea ''PTHREAD_CREATE_DETACHED''. | Primul parametru este un pointer la obiectul reprezentând atributele, iar al doilea parametru reprezintă starea dorită - unificabil/detașabil. Deoarece implicit sunt create fire unificabile (valoarea ''PTHREAD_CREATE_JOINABLE''), această funcţie trebuie apelată doar dacă se creează fire detașabile și în acest caz al doilea parametru trebuie să aibă valoarea ''PTHREAD_CREATE_DETACHED''. | ||
- | Chiar dacă un fir de execuţie este creat unificabil, el poate fi transformat ulterior într-un fir detașabil apelând funcţia ''pthread_detach''. Însă o data detașat, nu mai poate fi făcut unificabil la loc. | + | Chiar dacă un fir de execuţie este creat unificabil, el poate fi transformat ulterior într-un fir detașabil apelând funcţia ''pthread_detach''. Însă detașat, nu mai poate fi refăcut unificabil. |
==== Modificarea politicii de alocare a procesorului ==== | ==== Modificarea politicii de alocare a procesorului ==== | ||
- | Standardul POSIX definește 3 politici de alocare a procesorului : | + | Standardul POSIX definește 3 politici de alocare a procesorului: |
*SCHED_RR - round robin | *SCHED_RR - round robin | ||
Line 98: | Line 98: | ||
Politicile SCHED_RR și SCHED_FIFO sunt opţionale și sunt suportate DOAR de firele de execuţie real time. | Politicile SCHED_RR și SCHED_FIFO sunt opţionale și sunt suportate DOAR de firele de execuţie real time. | ||
- | Funcţia care este folosită pentru a schimba politica de execuţie a firelor este : | + | Funcţia care este folosită pentru a schimba politica de execuţie a firelor este: |
<code c> | <code c> | ||
Line 112: | Line 112: | ||
==== Modificarea priorităţii ==== | ==== Modificarea priorităţii ==== | ||
- | Pentru a schimba/verifica prioritatea firelor de execuţie dispunem de următoarele funcţii : | + | Pentru a schimba/verifica prioritatea firelor de execuţie dispunem de următoarele funcţii: |
<code c> | <code c> | ||
Line 125: | Line 125: | ||
De obicei stivele firelor de execuţie încep la limita unei pagini de memorie, iar orice dimensiune a lor este rotunjită până la limita următoarei pagini. La capătul stivei este adăugată de obicei o pagină pentru care nu avem drepturi de acces și astfel cele mai multe depășiri de stivă (stack overflows) vor genera semnalul SIGSEGV (deci un segmentation fault). | De obicei stivele firelor de execuţie încep la limita unei pagini de memorie, iar orice dimensiune a lor este rotunjită până la limita următoarei pagini. La capătul stivei este adăugată de obicei o pagină pentru care nu avem drepturi de acces și astfel cele mai multe depășiri de stivă (stack overflows) vor genera semnalul SIGSEGV (deci un segmentation fault). | ||
- | Dacă firul a fost creat unificabil stiva nu poate fi eliberată până nu se va termina un apel <tt>pthread_join</tt> pentru respectivul fir. | + | Dacă firul a fost creat unificabil stiva nu poate fi eliberată până nu se va termina un apel ''pthread_join'' pentru respectivul fir. |
- | De obicei biblioteca de fire de execuţie alocă 1M de memorie virtuală pentru fiecare stivă de fir de execuţie. | + | De obicei biblioteca de fire de execuţie alocă 2M de memorie virtuală pentru fiecare stivă de fir de execuţie. |
Limita minimă pentru dimensiunea unei stive a unui fir de execuţie este PTHREAD_STACK_MIN. | Limita minimă pentru dimensiunea unei stive a unui fir de execuţie este PTHREAD_STACK_MIN. | ||
- | Pentru a seta/afla dimensiunea stivei unui fir de execuţie se pot utiliza funcţiile : | + | Pentru a seta/afla dimensiunea stivei unui fir de execuţie se pot utiliza funcţiile: |
<code c> | <code c> | ||
Line 138: | Line 138: | ||
</code> | </code> | ||
- | Pentru a specifica adresa de început a unei stive se poate utiliza funcţia : | + | Pentru a specifica adresa de început a unei stive se poate utiliza funcţia: |
<code c> | <code c> |