This is an old revision of the document!
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.
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
).
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:
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.
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:
sleep 20
și procesul bash
nou creat.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
.
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:
cat /proc/$$/status
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ă.
Dacă rulăm 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.
Intrați în directorul ctxt-switch/
din arhiva cu demo-uri a cursului.
cpu.c
și io.c
.make
cpu
și io
.cpu
:./cpu
cat /proc/$(pidof cpu)/status
nonvoluntary_ctxt_switches
. Cum explicați?io
:./io
cat /proc/$(pidof io)/status
voluntary_ctxt_switches
. Cum explicați?voluntary_ctxt_switches
se face doar în cazul apelului sleep()
, nu și în cazul apelului write()
(apel de I/O)?fork-file-pointer/
din arhiva cu demo-uri a cursului.fork-file-pointer.c
.make
fork-file-pointer
.fork-file-pointer
:./fork-file-pointer
lsof -a -o -d 0-1023 -p $(pidof fork-file-pointer | cut -d ' ' -f 1)
OFFSET
.f.txt
după rularea programului:cat f.txt
fork()
, se partajează cursorul de fișier al fișierelor deschise înainte de fork()
.orphan-zombie/
din arhiva cu demo-uri a cursului.orphan.c
și zombie.c
.make
orphan
și zombie
.orphan
:./orphan
watch -n 1 ps -f -C orphan
init
.zombie
:./zombie
watch -n 1 ps -f -C zombie
ps
apare șirul <defunct>
.