Differences

This shows you the differences between two versions of the page.

Link to this comparison view

so:cursuri:curs-03 [2013/03/05 12:01]
razvan.deaconescu [Demo-uri]
so:cursuri:curs-03 [2019/03/02 09:07] (current)
razvan.deaconescu
Line 1: Line 1:
 ====== Curs 03 - Procese ====== ====== Curs 03 - Procese ======
  
-<​html>​ +/* 
-<iframe src="http://​prezi.com/embed/​q-s8q3mrycz5/?​bgcolor=ffffff&​amp;​lock_to_path=0&amp;​autoplay=no&​amp;​autohide_ctrls=0&​amp;​features=undefined&​amp;​disabled_features=undefined"​ width="​550"​ height="​400"​ frameBorder="​0"><​/iframe> +  * [[http://​prezi.com/​q-s8q3mrycz5/so-curs-3/?kw=view-q-s8q3mrycz5&rc=ref-31844697|Curs 03 - Procese (vizualizare Prezi)]] 
-</html>+*
 +  * [[http://​elf.cs.pub.ro/​so/​res/​cursuri/​SO%20-%20Curs%2003%20-%20Procese.pdf|Curs 03 - Procese (PDF)]]
  
-  * [[http://prezi.com/q-s8q3mrycz5/so-curs-3/?kw=view-q-s8q3mrycz5&​rc=ref-31844697 ​Curs 03 - Procese (vizualizare Prezi)]] +  * [[https://docs.google.com/document/d/1m5viP2CYF9P-ETMFPogiPsV1c8MlrFOAdBZVNemGNNY/edit?usp=sharing|Notițe de curs]]
-  * [[http://​elf.cs.pub.ro/​so/​res/​cursuri/​SO_Curs-03.pdf | Curs 03 - Procese (PDF)]]+
  
   * Suport curs   * Suport curs
     * Operating System Concepts Essentials     * Operating System Concepts Essentials
       * Capitolul 3 - Processes       * Capitolul 3 - Processes
-    * Modern Operating Systems+    * Modern Operating Systems ​(2nd Ed., 3rd Ed.)
       * Capitolul 2 - Processes and Threads - Secțiunea 1       * Capitolul 2 - Processes and Threads - Secțiunea 1
     * Linux System Programming     * Linux System Programming
Line 20: Line 20:
       * Capitolul 6 - Process Management       * Capitolul 6 - Process Management
       * Capitolul 11 - Interprocess Communication       * Capitolul 11 - Interprocess Communication
 +
 +/*
 +<​html>​
 +  <​center>​
 +    <iframe src="​https://​prezi.com/​embed/​q-s8q3mrycz5/?​bgcolor=ffffff&​amp;​lock_to_path=0&​amp;​autoplay=no&​amp;​autohide_ctrls=0&​amp;​features=undefined&​amp;​disabled_features=undefined"​ width="​550"​ height="​400"​ frameBorder="​0"></​iframe>​
 +  </​center>​
 +</​html>​
 +*/
 +
 +<​html>​
 +  <​center>​
 +    <iframe src="​https://​docs.google.com/​viewer?​url=https://​elf.cs.pub.ro/​so/​res/​cursuri/​SO%20-%20Curs%2003%20-%20Procese.pdf&​embedded=true"​ width="​600"​ height="​480"​ style="​border:​ none;">​
 +    </​iframe>​
 +  </​center>​
 +</​html>​
 +
  
 ===== Demo-uri ===== ===== Demo-uri =====
  
-Pentru parcurgerea demo-urilor, ​folosiți ​[[http://​elf.cs.pub.ro/​so/​res/​cursuri/​curs-03.zip|arhiva aferentă]].+Pentru parcurgerea demo-urilor, ​folosim ​[[http://​elf.cs.pub.ro/​so/​res/​cursuri/​curs-03-demo.zip|arhiva aferentă]]. ​Demo-urile rulează pe Linux. Descărcăm arhiva folosind comanda<​code bash> 
 +wget http://​elf.cs.pub.ro/​so/​res/​cursuri/​curs-03-demo.zip 
 +</​code>​ și apoi decomprimăm arhiva<​code bash> 
 +unzip curs-03-demo.zip 
 +</​code>​ și accesăm directorul rezultat în urma decomprimării<​code bash> 
 +cd curs-03-demo/​ 
 +</​code>​
  
-  - Folosiți comenzile ​de mai jos pentru ​a afișa informații despre procesul shell curent:<​code bash>+Acum putem parcurge secțiunile cu demo-uri ​de mai jos
 + 
 +==== Informații despre shell-ul curent ==== 
 + 
 +Pentru ​a afișa informații despre procesul shell curent, folosim comenzile de mai jos:<code bash>
 ps -f $$ ps -f $$
 ps -F $$ ps -F $$
Line 33: Line 59:
 cat /​proc/​$$/​status cat /​proc/​$$/​status
 </​code>​ </​code>​
-  ​Determinaținformații complete despre un proces creat (''​find''​), prin rularea comenzii de mai jos:<code bash>+ 
 +Aceste comenzi ne afișează infomații precum PID-ul procesului, comanda de la care a pornit, PID-ul procesului părinte, timpul de rulare, fișierele deschise (''​lsof''​),​ spațiul de adresă al procesului (''​pmap''​). 
 + 
 +==== Informații despre un proces din sistem ==== 
 + 
 +Dorim să aflăm ​informații complete despre un proces creat. Pentru aceea pornim în shell o comandă ​(''​find''​) ​care să creeze un proces:<code bash>
 /​usr/​bin/​time -v find /usr/share > /dev/null /​usr/​bin/​time -v find /usr/share > /dev/null
 </​code>​ </​code>​
-    * Parcurgeți câmpurile ​și determinați semnificația lor+ 
-    * //User time// este timpul petrecut de proces în user space//System time// este timpul petrecut de proces în kernel space//Elapsed (wall clock) time// este timpul trecut pe ceas. Procesul rulează pe procesor timp de //User time// + //System time//​. ​De ce este acest timp mai mic (cu mult) decât ​//​Elapsed ​(wall clock) ​time//. +Comanda ''​time''​ trebuie dată în cale completă (''/​usr/​bin/​time''​) pentru a nu rula comanda ''​time''​ internă shell-ului. 
-  - Afișați ierarhia ​curentă ​de procese a sistemului ​folosind ​comenzile de mai jos:<​code bash>+ 
 +Comanda permite rularea altei comenzi ​și afișarea de informații despre procesul creat de aceastaAstfel de informații sunt cel de timp: 
 +  * //User time// este timpul petrecut de proces în user space 
 +  * //System time// este timpul petrecut de proces în kernel space 
 +  * //Elapsed (wall clock) time// este timpul trecut pe ceas. 
 +Procesul rulează pe procesor timp de //User time// + //System time//​. ​Observăm că //Elapsed time// ​este mai mare decât timpul efectiv de rulare a procesului pe procesor. Acest lucru se întâmplă întrucât în acest timp au mai rulat și alte procese procesor, timp în care procesul curent a așteptat
 + 
 +==== Ierarhia de procese a sistemului ==== 
 + 
 +Pentru a afișa ierarhia de procese a sistemului ​folosim ​comenzile de mai jos:<​code bash>
 pstree pstree
 ps -H ps -H
 </​code>​ </​code>​
-  ​- Vrem să vizualizăm evoluția arborelui de procese. Vom vizualiza subarborele unui proces shell. +Rădăcina ierarhiei este procesul ''​init''​ (PID-ul 1), procesul părinte al sistemului. 
-    ​* ​Pentru început, ​aflați ​PID-ul procesului shell curent:<​code bash>+ 
 +Vrem să vizualizăm evoluția arborelui de procese. Vom vizualiza subarborele unui proces shell. 
 + 
 +Pentru început, ​aflăm ​PID-ul procesului shell curent:<​code bash>
 echo $$ echo $$
 </​code>​ </​code>​
-    * Fie ''​$PID''​ valorea afișată de comanda de mai sus. +Fie ''​$PID''​ valorea afișată de comanda de mai sus. Deschidem ​un shell nou și rulăm ​comanda:<​code bash>
-    * Deschideți ​un shell nou și rulați ​comanda:<​code bash>+
 watch -n 1 pstree -a -p $PID watch -n 1 pstree -a -p $PID
 </​code>​ </​code>​
-      * Comanda de mai sus vă afișează, cu refresh de o secundă, ierarhia de procese începând cu shell-ul inițial. +Comanda de mai sus afișează, cu refresh de o secundă, ierarhia de procese începând cu shell-ul inițial. 
-    ​* ​Pentru a altera ierarhia, ​rulați ​comenzile de mai jos. Observați evoluția ierarhiei în al doilea shell:<code bash>+ 
 +Pentru a altera ierarhia, ​rulăm ​comenzile de mai jos:<​code bash>
 sleep 20 & sleep 20 &
 bash bash
Line 57: Line 100:
 exit exit
 </​code>​ </​code>​
-      * Cum explicați alterarea ierahiei, apariția și dispariția anumitor procese ​și poziționarea lor în ierarhie+Observăm evoluția ierarhiei în al doilea shell: 
-  ​Pentru a urmări numărul de schimbări de context ale unui proces, ​consultați ​fișierul ''/​proc/​$PID/​status''​, și anume câmpurile ''​voluntary_ctxt_switches''​ și ''​nonvoluntary_ctxt_switches''​. ​Urmăriți aceste valori pentru shell-ul curent:<​code bash>+  * La început se creează un proces sleep pe post de proces copil. Este rulat în background deci revine controlul shell-ului curent. 
 +  * Shell-ul curent creează un alt shell. Acum shell-ul curent are două procese copil: procesul ''​sleep 20'' ​și procesul ''​bash''​ nou creat. 
 +  * Shell-ul cel nou creează ​și el la rândul său un proces ''​sleep''​ și așteaptă încheierea sa. În acest moment shell-ul inițial are un proces copil ''​sleep'',​ un proces copil ''​bash''​ și un proces "​nepot"​ ''​sleep''​
 +  ​* La încheierea rulării execuției proceselor, ierarhia se destramă. 
 + 
 +==== Informații despre schimbările de context ==== 
 + 
 +Pentru a urmări numărul de schimbări de context ale unui proces, ​consultăm ​fișierul ''/​proc/​$PID/​status''​. Ne interesează ​câmpurile ''​voluntary_ctxt_switches''​ și ''​nonvoluntary_ctxt_switches''​. ​Pentru a urmări aceste valori pentru shell-ul curent ​folosim comanda:<code bash>
 cat /​proc/​$$/​status cat /​proc/​$$/​status
 </​code>​ </​code>​
-    * Ce semnifică fiecare dintre cele două câmpuri ​de mai sus? + 
-    * Rulați de mai multe ori comanda de mai sus și observați alterarea celor două câmpuri. ​De ce se alterează ​proponderent ​câmpul ''​voluntary_ctxt_switches''​+Câmpul ''​voluntary_ctxt_switches''​ (schimbări de context voluntare) se referă la schimbările în care procesul lasă de bună voie procesorul, de obicei acțiuni blocante de intrare/​ieșire. Câmpul ''​nonvoluntary_ctxt_switcher''​ (schimbări de context nevoluntar) se referă la schimbările în care procesul este dat la o parte de pe procesor; de obicei acest lucru înseamnă expirarea cuantei curente de rulare; poate fi vorba și de apariția unui proces de prioritate ​mai bună. 
-  ​Intrați în directorul ''​ctxt-switch/''​ din arhiva cu demo-uri a cursului. + 
-    * Parcurgeți ​fișierele ''​cpu.c''​ și ''​io.c''​. +Dacă rulăm de multe ori comanda de mai sus (''​cat /​proc/​$$/​status''​) vom observa alterarea celor două câmpuri. ​Se alterează ​preponderent ​câmpul ''​voluntary_ctxt_switches'' ​întrucât procesul curent, shell-ul, așteaptă în general intrare de la utilizator. Făcând în majoritate acțiuni de intrare/​ieșire (blocante), cele mai dese schimbări de context sunt cele voluntare. 
-    * Compilațcele două programe folosind comanda:<code bash>+ 
 +==== I/O bound vs. CPU bound ==== 
 + 
 +Vrem să observăm diferența tipurilor de schimbări de context pentru procese I/O bound șprocese CPU bound. Vom folosi ​directorul ''​ctxt-switch/''​ din arhiva cu demo-uri a cursului. 
 + 
 +Parcurgem ​fișierele ''​cpu.c''​ și ''​io.c''​. ​Observăm că ''​cpu.c''​ face multe acțiuni (consumă procesor), în timp ce ''​io.c''​ face operații blocante. Compilăm ​cele două programe folosind comanda<​code bash>
 make make
-</​code>​ +</​code> ​și obținem executabilele ''​cpu''​ și ''​io''​. 
-      * Veți obține executabilele ''​cpu''​ și ''​io''​. + 
-    * Rulați ​executabilul ''​cpu'':<​code bash>+Întâi rulăm ​executabilul ''​cpu'':<​code bash>
 ./cpu ./cpu
 </​code>​ </​code>​
-      * Într-o altă consolă urmăriți numărul de context ​switch-uri ​realizate de procesul nou creat:<​code bash>+Într-o altă consolă urmărim numărul ​de schimbări ​de context realizate de procesul nou creat:<​code bash>
 cat /​proc/​$(pidof cpu)/status cat /​proc/​$(pidof cpu)/status
 </​code>​ </​code>​
-      * Observați ​că se modifică preponderent valoarea câmpului ''​nonvoluntary_ctxt_switches''​. ​Cum explicați+Observăm ​că se modifică preponderent valoarea câmpului ''​nonvoluntary_ctxt_switches''​. ​Acest lucru se întâmplă pentru că avem un proces CPU-bound. Acesta va consuma timp de procesor ori de câte ori prinde ocazia șva fi dat afară în majoritar la expirarea cuantei (nu face operații blocante). Un astfel de proces poartă numele de //CPU hog//. 
-    * Rulațexecutabilul ''​io'':<​code bash>+ 
 +Apoi rulăm ​executabilul ''​io'':<​code bash>
 ./io ./io
 </​code>​ </​code>​
-      * Într-o altă consolă urmăriți numărul de context ​switch-uri ​realizate de procesul nou creat:<​code bash>+Într-o altă consolă urmăriți numărul ​de schimbări ​de context realizate de procesul nou creat:<​code bash>
 cat /​proc/​$(pidof io)/status cat /​proc/​$(pidof io)/status
 </​code>​ </​code>​
-      * Observați ​că se modifică preponderent valoarea câmpului ''​voluntary_ctxt_switches''​. ​Cum explicați? +Observăm ​că se modifică preponderent valoarea câmpului ''​voluntary_ctxt_switches''​. ​Acest lucru se întâmplă pentru că avem un proces IO-bound. Acesta va executa multe operații blocante ​în cadrul cărora va ceda de bună voie procesorul. 
-      * De ce în modificarea câmpului ​''​voluntary_ctxt_switches''​ se face doar în cazul apelului ​''​sleep()''​nu și în cazul apelului ​''​write()'' ​(apel de I/O)+ 
-  ​Intrați ​în directorul ''​fork-file-pointer/''​ din arhiva cu demo-uri a cursului. +La o privire mai atentă la câmpul ​''​voluntary_ctxt_switches'' ​pentru procesul creat din executabilul ''​io'',​ observăm că acesta ​se modifică ​doar la apelul ​''​sleep''​ nu și la apelul ​''​write''​, deși ''​write''​ este un apel I/O cu probabilitate ​de a se bloca. În realitate însă un apel ''​write''​ nu va copia date pe disc (sau la alt dispozitiv ​I/O) ci într-un buffer intern al nucleului. După copierea datelor ​în buffer-ul intern al nucleului, apelul ''​write''​ se întoarce, neexistând partea de blocare. 
-    * Parcurgeți ​fișierele ​''​fork-file-pointer.c''​. +==== Cursorul de fișier la fork ==== 
-    * Compilațcele două programe ​folosind comanda:<​code bash>+ 
 +Pentru a urmări comportamentului cursorului de fișier (//file pointerului//​) vom folosi ​directorul ''​fork-file-pointer/''​ din arhiva cu demo-uri a cursului. 
 + 
 +Vom parcurge ​fișierul ''​fork-file-pointer.c''​. ​Observăm că acelașdescriptor de fișier este folosit și de procesul copil și de procesul părinte. Vrem să vedem dacă aceste ​două procese partajează cursorul de fișier. 
 + 
 +Pentru început compilăm programul ​folosind comanda:<​code bash>
 make make
 </​code>​ </​code>​
-      * Veți obține executabilele ​''​fork-file-pointer''​. +Obținem executabilul ​''​fork-file-pointer''​. ​Rulăm ​executabilul:<​code bash>
-    * Rulați ​executabilul ​''​fork-file-pointer''​:<code bash>+
 ./​fork-file-pointer ./​fork-file-pointer
 </​code>​ </​code>​
-      * Într-o altă consolă urmăriți evoluția cursorului de fișier pentru procesul creat (procesul părinte) folosind comanda:<​code bash>+ 
 +Într-o altă consolă urmărim evoluția cursorului de fișier pentru procesul creat (procesul părinte) folosind comanda:<​code bash>
 lsof -a -o -d 0-1023 -p $(pidof fork-file-pointer | cut -d ' ' -f 1) lsof -a -o -d 0-1023 -p $(pidof fork-file-pointer | cut -d ' ' -f 1)
 </​code>​ </​code>​
-        * Cursorul de fișier este indicat de coloana ''​OFFSET''​. +Observăm modificarea cursorului de fișier de la valoarea ''​0''​ la valoarea ''​10''​ apoi la valoarea ''​20''​ apoi la valoarea ''​30''​. 
-      * Vizualizați ​conținutul fișierului ''​f.txt'' ​după rularea programului:<code bash>+ 
 +<note tip> 
 +Cursorul de fișier este indicat de coloana ''​OFFSET''​. 
 +</​note>​ 
 +După încheierea procesului urmărim ​conținutul fișierului ''​f.txt'':<​code bash>
 cat f.txt cat f.txt
 </​code>​ </​code>​
-    * Se observă că, în urma ''​fork()'',​ se partajează cursorul de fișier al fișierelor deschise înainte ''​fork()''​. + 
-  - Intrați în directorul ''​orphan-zombie/''​ din arhiva cu demo-uri a cursului. +Observăcă fiecare proces (părinte sau copil) a scris în continuarea celuilalt. Adică, în urma ''​fork()'',​ se partajează cursorul de fișier al fișierelor deschise înainte ​de ''​fork()''​. Procesul părinte partajează cursorul de fișier cu procesele copil
-    * Parcurgeți ​fișierele ''​orphan.c''​ și ''​zombie.c''​. +==== Procese orfane și procese zombie ==== 
-    * Compilați cele două programe folosind comanda:<code bash>+ 
 +Vrem să urmărim apariția proceselor orfane șa proceselor zombie și să le investigăm. Pentru aceasta vom folosi ​directorul ''​orphan-zombie/''​ din arhiva cu demo-uri a cursului. 
 + 
 +Parcurgem ​fișierele ''​orphan.c''​ și ''​zombie.c''​. ​Primul program creează un proces orfan, adică își încheie execuția procesul părinte, dar procesul copil continuă execuția. Al doilea program creează un proces zombie, adică procesul copil îșîncheie execuția, dar procesul părinte continuă execuția fără a aștepta procesul copil. 
 + 
 +Compilăm ​cele două programe folosind comanda<​code bash>
 make make
-</​code>​ +</​code> ​ și obținem executabilele ''​orphan''​ și ''​zombie''​. 
-      * Veți obține executabilele ''​orphan''​ și ''​zombie''​. + 
-    * Rulați ​executabilul ''​orphan'':<​code bash>+Rulăm ​executabilul ''​orphan'':<​code bash>
 ./orphan ./orphan
 </​code>​ </​code>​
-      * Într-o altă consolă urmăriți PID-urile și PPID-urile celor două procese (părinte și copil):<​code bash>+Într-o altă consolă urmărim PID-urile și PPID-urile celor două procese (părinte și copil):<​code bash>
 watch -n 1 ps -f -C orphan watch -n 1 ps -f -C orphan
 </​code>​ </​code>​
-      * Urmăriți mesajele afișate de procesul copil. Mesajele vor fi afișate și după terminarea procesului părinte. +Urmărim mesajele afișate de procesul copil. Mesajele vor fi afișate și după terminarea procesului părinte. ​Observăm ​actualizarea PID-ului procesului părinte (PPID) pentru procesul copil: după ce a rămas orfan, ​procesul ​copil a fost adoptat de ''​init'' ​(procesul cu PID-ul ''​1''​)
-      * Observați ​actualizarea PID-ului procesului părinte (PPID) pentru procesul copil. Observați înfierea acestuia de procesul ''​init''​. + 
-    * Rulați ​executabilul ''​zombie'':<​code bash>+Rulăm ​executabilul ''​zombie'':<​code bash>
 ./zombie ./zombie
 </​code>​ </​code>​
-      * Într-o altă consolă urmăriți cele două procese (părinte și copil):<​code bash>+Într-o altă consolă urmărim cele două procese (părinte și copil):<​code bash>
 watch -n 1 ps -f -C zombie watch -n 1 ps -f -C zombie
 </​code>​ </​code>​
-      * Observați ​trecerea procesului copil în starea //zombie//; în ieșirea comenzii ''​ps''​ apare șirul ''<​defunct>''​. +Observăm ​trecerea procesului copil în starea //zombie//; în ieșirea comenzii ''​ps''​ apare șirul ''<​defunct>''​. ​Observăm ​eliminarea procesului //zombie// după așteptarea sa de procesul părinte
-      * Observați ​eliminarea procesului //zombie// după așteptarea sa de procesul părinte.+ 
 +Un proces este //zombie// pentru că reține niște informație reziduală legată de modul în care și-a încheiat execuția; această informație reziduală este utilă procesului părinte. În momentul în care procesul părinte citește această informație reziduală folosind un apel din familia ''​wait'',​ procesul copil, acum //zombie//, își încheie complet execuția și dispare din sistem.
so/cursuri/curs-03.1362477714.txt.gz · Last modified: 2013/03/05 12:01 by razvan.deaconescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0