This shows you the differences between two versions of the page.
so:laboratoare:resurse:recapitulare [2013/01/31 21:57] 127.0.0.1 external edit |
so:laboratoare:resurse:recapitulare [2022/03/14 18:02] (current) teodor_stefan.dutu [Exerciții] Rework exercise 1 |
||
---|---|---|---|
Line 3: | Line 3: | ||
Laboratorul constă în subiecte în stilul celor de la examen, însoțite de mici bucăți de cod complete sau aproape complete pe care le puteți rula pentru a vă convinge. Discuția pe marginea subiectelor cu asistentul sau cu colegii este încurajată. Subiectele sunt suficient de multe încât nu pot fi acoperite într-un singur laborator. | Laboratorul constă în subiecte în stilul celor de la examen, însoțite de mici bucăți de cod complete sau aproape complete pe care le puteți rula pentru a vă convinge. Discuția pe marginea subiectelor cu asistentul sau cu colegii este încurajată. Subiectele sunt suficient de multe încât nu pot fi acoperite într-un singur laborator. | ||
===== Exerciții ===== | ===== Exerciții ===== | ||
- | Utilizați arhiva [[http://elf.cs.pub.ro/so/wiki/_media/laboratoare/resurse/recap.tar.gz | recap.tar.gz]] aferentă laboratorului. | ||
- | # Demand-paging, Copy-on-Write. Intrați în directorul {{{01-cow-dp}}}. | + | - Demand-paging, Copy-on-Write. Intrați în directorul ''01-cow''. |
- | #* Rulați comanda:<code> | + | * Rulați comanda ''make'' și rulați executabilul creat: ''cow''. |
- | make && make run | + | * **Explicați** când au loc evenimentele de Demand-paging și de Copy-on-Write. |
- | </code> | + | * De ce scrierea efectuată de procesul copil în paginile alocate de părinte dureaza mult mai mult decât citirile? |
- | #* **Explicați** apariția evenimentelor de Demand-paging și de Copy-on-Write. | + | - Subsistemul IO. Intraţi în directorul ''02-io'' şi inspectaţi fişierul ''splice.c''. |
- | #* Pentru testare, utilizați fișierele: {{{fault/fault}}} și {{{fault2/fault}}}. | + | * Închipuiţi-vă scenariul în care programul rulează repede şi un alt scenariu în care rulează greu (din punctul de vedere al timpului). |
- | #* De ce la ultima pagină din buffer (din fișierul {{{fault/fault}}}) nu se mai face Demand-paging? | + | * **Hints**: |
- | #* **Hints**: | + | * Ce operaţii se fac la trunchierea fişierului? |
- | #** paginile **gri** reprezintă pagini muliple nemapate reprezentate într-un interval | + | * Care este rolul fişierului [[http://www.linuxinsight.com/proc_sys_vm_drop_caches.html | /proc/sys/vm/drop_caches]]? |
- | #** paginile **verzi** reprezintă pagini ce aparțin unui singur proces | + | * Ce fel de mecanism implementează apelul de sistem ''splice''? |
- | #** paginile **roșii** sunt pagini partajate de cel puțin două procese | + | * **Atenţie**: Asigurați-vă că sistemul dispune de suficientă memorie (RAM) liberă pentru a putea aduce tot fișierul în RAM (i.e. dimensiunea memorie liberă > dimensiunea fișierului). |
- | #** la **click** pe o pagină se centrează pagina respectivă și toate paginile legate de ea | + | * Utilizaţi scriptul ''run.sh'': <code>sudo ./run.sh</code> |
- | #** după ce a a apărut un eveniment de tipul Copy-on-Write **un** click duce la pagina la care este mapată acum, **următorul** click va duce la pagina veche la care era mapată | + | * **Ignoraţi mesajul**:<code>Command terminated by signal 13</code> |
- | # Subsistemul IO. Intraţi în directorul {{{02-io}}} şi inspectaţi fişierul {{{splice.c}}}. | + | - Threads counter (LD): Un proces crează N thread-uri și un thread apelează fork(); câte threaduri, atât în procesul părinte cât și în procesul copil, există imediat după acest moment? Studiați conținutul directorului ''03-threads-counter''. În ce director din ''/proc/$PID/'' se află informațiile despre thread-urile procesului? De ce acestea au asignat un pid? |
- | #* Închipuiţi-vă scenariul în care programul rulează repede şi un alt scenariu în care rulează greu (din punctul de vedere al timpului). | + | - Function hijacking (LD): De ce în cazul folosirii LD_PRELOAD se pot intercepta apeluri de funcții? Intrați în directorul ''04-functions-hijacking'', compilați (''make'') și rulați (''./test'' și ''LD_PRELOAD=./libnative.so ./test''. Cum explicați output-ul diferit? |
- | #* **Hints**: | + | - Inițializări (VD): Intrați în directorul ''05-init''. Compilați programul ''initializari''. De ce durează mai mult prima inițializare? De asemenea, încercați să explicați dimensiunea mare a executabilului. |
- | #** Ce operaţii se fac la trunchierea fişierului? | + | - Spațiu de adresă (AF): Intrați în directorul ''06-addrspc'' și inspectați fișierul ''addrspc.c''. Ce se întâmplă cu spațiul de adresă al procesului în momentul schimbării de context? |
- | #** Care este rolul fişierului [[http://www.linuxinsight.com/proc_sys_vm_drop_caches.html | /proc/sys/vm/drop_caches]] | + | * **Hints**: |
- | #** Ce fel de mecanism implementează apelul de sistem {{{splice}}}? | + | * Threadurile rulează alternativ, scriind la stdout atunci când încep rularea |
- | #** **Atenţie**: Asigurați-vă că sistemul dispune de suficientă memorie (RAM) liberă pentru a putea aduce tot fișierul în RAM (i.e. dimensiunea memorie liberă > dimensiunea fișierului). | + | * Monitorizați ''/proc/$PID/maps'' |
- | #** Utilizaţi scriptul {{{run.sh}}}: <code>sudo ./run.sh</code> | + | - Reentranță / thread-safety (AF): Catalogați funcțiile din ''07-reentr/reentr.c'' ca fiind reentrante / thread-safe. Puteți modifica programul încât să puneți în evidență aceste aspecte. |
- | #** **Ignoraţi mesajul**:<code>Command terminated by signal 13</code> | + | - Stack growth (VD): Scrieți o secvență de cod care să decidă dacă stiva crește în sus sau în jos. Un asemenea exemplu îl aveți în directorul ''08-stack-growth''. |
- | # Threads counter (LD): Un proces crează N thread-uri și un thread apelează fork(); câte threaduri, atât în procesul părinte cât și în procesul copil, există imediat după acest moment? Studiați conținutul directorului {{{03-threads-counter}}}.În ce director din {{{/proc/$PID/}}} se află informațiile despre thread-urile procesului? De ce acestea au asignat un pid? | + | - Apeluri de sistem (DB): Câte apeluri de sistem se efectuează în urma rulării secvenţei de mai jos:<code c> |
- | # Function hijacking (LD): De ce în cazul folosirii LD_PRELOAD se pot intercepta apeluri de funcții? Intrați în directorul {{{04-functions-hijacking}}}, compilați ({{{make}}}) și rulați ({{{./test}}} și {{{LD_PRELOAD=./libnative.so ./test}}}. Cum explicați output-ul diferit? | + | |
- | # Inițializări (VD): Intrați în directorul {{{05-init}}}. Compilați programul {{{initializari}}}. De ce durează mai mult prima inițializare? De asemenea, încercați să explicați dimensiunea mare a executabilului. | + | |
- | # Spațiu de adresă (AF): Intrați în directorul {{{06-addrspc}}} și inspectați fișierul {{{addrspc.c}}}. Ce se întâmplă cu spațiul de adresă al procesului în momentul schimbării de context? | + | |
- | #* **Hints**: | + | |
- | #** Threadurile rulează alternativ, scriind la stdout atunci când încep rularea | + | |
- | #** Monitorizați {{{/proc/$PID/maps}}} | + | |
- | # Reentranță / thread-safety (AF): Catalogați funcțiile din {{{07-reentr/reentr.c}}} ca fiind reentrante / thread-safe. Puteți modifica programul încât să puneți în evidență aceste aspecte. | + | |
- | # Stack growth (VD): Scrieți o secvență de cod care să decidă dacă stiva crește în sus sau în jos. Un asemenea exemplu îl aveți în directorul {{{08-stack-growth}}}. | + | |
- | # Apeluri de sistem (DB): Câte apeluri de sistem se efectuează în urma rulării secvenţei de mai jos:<code c> | + | |
for (i = 0; i < 10; i++) { | for (i = 0; i < 10; i++) { | ||
getpid(); | getpid(); | ||
Line 42: | Line 32: | ||
} | } | ||
</code> | </code> | ||
- | #* Intrați în directorul {{{09-syscall}}}. | + | * Intrați în directorul ''09-syscall''. |
- | #* Analizaţi conţinutul fişierului {{{pid_test.c}}}. | + | * Analizaţi conţinutul fişierului ''pid_test.c''. |
- | #* Urmăriţi apelurile de system efectuate rulând comanda ''strace''. <code bash> | + | * Urmăriţi apelurile de system efectuate rulând comanda ''strace''. <code bash> |
strace ./pid_test | strace ./pid_test | ||
</code> | </code> | ||
- | #* **Suplimentar** | + | * **Suplimentar** |
- | #** Analizaţi conţinutul fişierului {{{fork_test.c}}}. | + | * Analizaţi conţinutul fişierului ''fork_test.c''. |
- | #** Rulaţi programul având pentru ''SYS_TYPE'' pe rând valorile ''SYS_NATIVE'' şi ''SYS_GLIBC''. | + | * Rulaţi programul având pentru ''SYS_TYPE'' pe rând valorile ''SYS_NATIVE'' şi ''SYS_GLIBC''. *Explicaţi rezultatul obţinut. Citiţi secţiunea ''NOTES'' din ''getpid(2)''. |
- | #** Explicaţi rezultatul obţinut. Citiţi secţiunea ''NOTES'' din ''getpid(2)''. | + | - Creare procese (DB): Desenaţi arborele de procese rezultat în urma execuţiei programului ''fork.c'' din directorul ''10-fork''. |
- | # Creare procese (DB): Desenaţi arborele de procese rezultat în urma execuţiei programului ''fork.c'' din directorul {{{10-fork}}}. | + | - Descriptori de fisier (OB): Un proces dispune de o tabelă de descriptori de fișiere cu 1024 de intrări. În codul său, procesul deschide un număr mare de fișiere folosind open. Totuși, al 964-lea apel open se întoarce cu eroare, iar errno are valoarea EMFILE (maximum number of files open). Care este o posibilă explicație? Vă puteți gândi și la alte explicații decât cea din exemplu? |
- | # Descriptori de fisier (OB): Un proces dispune de o tabelă de descriptori de fișiere cu 1024 de intrări. În codul său, procesul deschide un număr mare de fișiere folosind open. Totuși, al 964-lea apel open se întoarce cu eroare, iar errno are valoarea EMFILE (maximum number of files open). Care este o posibilă explicație? Vă puteți gândi și la alte explicații decât cea din exemplu? | + | - File descriptor (BD): Completați zona punctată de mai jos cu cod Linux(posix) astfel incat sa conduca la afișarea mesajului "alfa" la ieșirea standard (standard output) și mesajul "beta" la ieșirea de eroare standard (standard error), fara sa alterați simbolurile standard fputs (functie), stderr și stdout (FILE *): |
- | # File descriptor (BD): Completați zona punctată de mai jos cu cod Linux(posix) astfel incat sa conduca la afișarea mesajului "alfa" la ieșirea standard (standard output) și mesajul "beta" la ieșirea de eroare standard (standard error), fara sa alterați simbolurile standard fputs (functie), stderr și stdout (FILE *): | + | * <code> |
- | #* <code> | + | |
/* de completat */ | /* de completat */ | ||
... | ... | ||
Line 60: | Line 49: | ||
fputs("beta", stdout); | fputs("beta", stdout); | ||
</code> | </code> | ||
- | #* Intrati in directorul {{{12-file}}}, si rulati comanda <code>./file >out 2>err </code> | + | * Intrati in directorul ''12-file'', si rulati comanda <code>./file >out 2>err </code> |
- | # Calloc/Malloc (IS): Intrați in directorul {{{13-access}}}. Rulați cele 2 programe atât cu macro-ul TEST_ACCESS definit cât și fără acesta. Măsurați timpii de rulare folosind //time// și încercați să explicați diferența. | + | - Calloc/Malloc (IS): Intrați in directorul ''13-access''. Rulați cele 2 programe atât cu macro-ul TEST_ACCESS definit cât și fără acesta. Măsurați timpii de rulare folosind //time// și încercați să explicați diferența. |
- | # Apeluri de sistem (RD): În urma rulării secvenței de mai jos:<code> | + | - Apeluri de sistem (RD): În urma rulării secvenței de mai jos:<code> |
int page_size = getpagesize(); | int page_size = getpagesize(); | ||
for (i = 0; i < 1000; i++) | for (i = 0; i < 1000; i++) | ||
ptr[i] = malloc(page_size); | ptr[i] = malloc(page_size); | ||
- | </code> se obține un număr redus de apeluri de sistem, de ordinul zecilor (apelul de sistem folosit de malloc este {{{brk}}}). Cum explicați? | + | </code> se obține un număr redus de apeluri de sistem, de ordinul zecilor (apelul de sistem folosit de malloc este ''brk''). Cum explicați? |
- | #* Intrați în directorul {{{14-malloc-syscalls}}}. | + | * Intrați în directorul ''14-malloc-syscalls''. |
- | #* Urmăriți conținutul fișierului {{{malloc-syscalls.c}}}. | + | * Urmăriți conținutul fișierului ''malloc-syscalls.c''. |
- | #* Compilați fișierul (folosiți {{{make}}}). | + | * Compilați fișierul (folosiți ''make''). |
- | #* Rulați comanda {{{strace -e brk ./malloc-syscall 2>&1 > /dev/null | wc -l}}}. | + | * Rulați comanda ''strace -e brk ./malloc-syscall 2>&1 > /dev/null | wc -l''. |
- | #* Rulați comanda {{{ltrace -e malloc ./malloc-syscall 2>&1 > /dev/null | wc -l}}}. | + | * Rulați comanda ''ltrace -e malloc ./malloc-syscall 2>&1 > /dev/null | wc -l''. |
- | #* **Suplimentar** | + | * **Suplimentar** |
- | #** Actualizați macro-ul {{{DO_FREE}}} la valoarea 1. | + | * Actualizați macro-ul ''DO_FREE'' la valoarea 1. |
- | #** Câte apeluri {{{brk}}} au loc? Cum explicați? Ce rol are apelul de sistem {{{brk}}}? | + | * Câte apeluri ''brk'' au loc? Cum explicați? Ce rol are apelul de sistem ''brk''? |
- | # Page fault-uri (RD): Câte page fault-uri se obțin în urma rulării secvenței de mai jos?<code> | + | - Page fault-uri (RD): Câte page fault-uri se obțin în urma rulării secvenței de mai jos?<code> |
char *p; | char *p; | ||
int status; | int status; | ||
Line 117: | Line 106: | ||
p[i*page_size] = i; | p[i*page_size] = i; | ||
</code> | </code> | ||
- | #* Intrați în directorul {{{15-faults}}}. | + | * Intrați în directorul ''15-faults''. |
- | #* Urmăriți conținutul fișierului {{{fork-faults.c}}}. | + | * Urmăriți conținutul fișierului ''fork-faults.c''. |
- | #* Compilați fișierul (folosiți {{{make}}}). | + | * Compilați fișierul (folosiți ''make''). |
- | #* Instalați pachetul {{{sysstat}}}. Pachetul conține utilitarul {{{pidstat}}} care permite monitorizarea page fault-urilor unui proces (prin intermediul argumentului {{{-r}}}). | + | * Instalați pachetul ''sysstat''. Pachetul conține utilitarul ''pidstat'' care permite monitorizarea page fault-urilor unui proces (prin intermediul argumentului ''-r''). |
- | #* Rulați programul {{{fork-faults}}}. Folosiți {{{ENTER}}} pentru a continua programul. | + | * Rulați programul ''fork-faults''. Folosiți ''ENTER'' pentru a continua programul. |
- | #* Folosiți comanda {{{pidstat -r -T ALL -p $PID}}} pentru a urmări page fault-urile. Rulați comanda pentru fiecare secvență de program. | + | * Folosiți comanda ''pidstat -r -T ALL -p $PID'' pentru a urmări page fault-urile. Rulați comanda pentru fiecare secvență de program. |
- | #** {{{$PID}}} reprezintă pid-ul unui proces. Puteți afla atât pid-ul procesului părinte cât și pe cel al procesului copil cu o comandă de forma {{{ps -ef | grep fork-faults}}}. | + | * ''$PID'' reprezintă pid-ul unui proces. Puteți afla atât pid-ul procesului părinte cât și pe cel al procesului copil cu o comandă de forma ''ps -ef | grep fork-faults''. |
- | #* Urmăriți evoluția numărului de page fault-uri pentru cele două procese: părinte și copil. Page fault-urile care apar în cazul unui copy-on-write în procesul copil vor fi vizibile ulterior și în procesul părinte. | + | * Urmăriți evoluția numărului de page fault-uri pentru cele două procese: părinte și copil. Page fault-urile care apar în cazul unui copy-on-write în procesul copil vor fi vizibile ulterior și în procesul părinte. |