This is an old revision of the document!


Curs 03 - Procese

  • Suport curs
    • Operating System Concepts Essentials
      • Capitolul 3 - Processes
    • Modern Operating Systems
      • Capitolul 2 - Processes and Threads - Secțiunea 1
    • Linux System Programming
      • Capitolul 5 - Process Management
      • Capitolul 6 - Advanced Process Management
      • Capitolul 9 - Signals
    • Windows System Programming
      • Capitolul 6 - Process Management
      • Capitolul 11 - Interprocess Communication

Demo-uri

Pentru parcurgerea demo-urilor, folosim arhiva aferentă. Demo-urile rulează pe Linux. Descărcăm arhiva folosind comanda

wget http://elf.cs.pub.ro/so/res/cursuri/curs-03-demo.zip

și apoi decomprimăm arhiva

unzip curs-03-demo.zip

și accesăm directorul rezultat în urma decomprimării

cd curs-03-demo/

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:

ps -f $$
ps -F $$
lsof -p $$
pmap $$
ls /proc/$$/
cat /proc/$$/status

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:

/usr/bin/time -v find /usr/share > /dev/null

Comanda time trebuie dată în cale completă (/usr/bin/time) pentru a nu rula comanda time internă shell-ului.

Comanda permite rularea altei comenzi și afișarea de informații despre procesul creat de aceasta. Astfel 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:

pstree
ps -H

Rădăcina ierarhiei este procesul init (PID-ul 1), procesul părinte al sistemului.

Vrem să vizualizăm evoluția arborelui de procese. Vom vizualiza subarborele unui proces shell.

Pentru început, aflăm PID-ul procesului shell curent:

echo $$

Fie $PID valorea afișată de comanda de mai sus. Deschidem un shell nou și rulăm comanda:

watch -n 1 pstree -a -p $PID

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, rulăm comenzile de mai jos:

sleep 20 &
bash
sleep 30       # asteptati terminarea comenzii
exit

Observăm evoluția ierarhiei în al doilea shell:

  • 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, 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:

cat /proc/$$/status
  • 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?

I/O bound vs. CPU bound

Intrați în directorul ctxt-switch/ din arhiva cu demo-uri a cursului.

  • Parcurgeți fișierele cpu.c și io.c.
  • Compilați cele două programe folosind comanda:
    make
    • Veți obține executabilele cpu și io.
  • Rulați executabilul cpu:
    ./cpu
    • Într-o altă consolă urmăriți numărul de context switch-uri realizate de procesul nou creat:
      cat /proc/$(pidof cpu)/status
    • Observați că se modifică preponderent valoarea câmpului nonvoluntary_ctxt_switches. Cum explicați?
  • Rulați executabilul io:
    ./io
    • Într-o altă consolă urmăriți numărul de context switch-uri realizate de procesul nou creat:
      cat /proc/$(pidof io)/status
    • Observați că se modifică preponderent valoarea câmpului voluntary_ctxt_switches. Cum explicați?
    • 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)?

Cursorul de fișier la fork

  1. Intrați în directorul fork-file-pointer/ din arhiva cu demo-uri a cursului.
    • Parcurgeți fișierele fork-file-pointer.c.
    • Compilați cele două programe folosind comanda:
      make
      • Veți obține executabilele fork-file-pointer.
    • Rulați executabilul fork-file-pointer:
      ./fork-file-pointer
      • Într-o altă consolă urmăriți evoluția cursorului de fișier pentru procesul creat (procesul părinte) folosind comanda:
        lsof -a -o -d 0-1023 -p $(pidof fork-file-pointer | cut -d ' ' -f 1)
        • Cursorul de fișier este indicat de coloana OFFSET.
      • Vizualizați conținutul fișierului f.txt după rularea programului:
        cat f.txt
    • Se observă că, în urma fork(), se partajează cursorul de fișier al fișierelor deschise înainte de fork().

Procese orfane și procese zombie

  1. Intrați în directorul orphan-zombie/ din arhiva cu demo-uri a cursului.
    • Parcurgeți fișierele orphan.c și zombie.c.
    • Compilați cele două programe folosind comanda:
      make
      • Veți obține executabilele orphan și zombie.
    • Rulați executabilul orphan:
      ./orphan
      • Într-o altă consolă urmăriți PID-urile și PPID-urile celor două procese (părinte și copil):
        watch -n 1 ps -f -C orphan
      • Urmăriți mesajele afișate de procesul copil. Mesajele vor fi afișate și după terminarea procesului părinte.
      • Observați actualizarea PID-ului procesului părinte (PPID) pentru procesul copil. Observați înfierea acestuia de procesul init.
    • Rulați executabilul zombie:
      ./zombie
      • Într-o altă consolă urmăriți cele două procese (părinte și copil):
        watch -n 1 ps -f -C zombie
      • Observați trecerea procesului copil în starea zombie; în ieșirea comenzii ps apare șirul <defunct>.
      • Observați eliminarea procesului zombie după așteptarea sa de procesul părinte.
so/cursuri/curs-03.1393892462.txt.gz · Last modified: 2014/03/04 02:21 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