This is an old revision of the document!
Examen
Examen final
Puteți participa la un singur examen final.
Datele de examen de SO sunt:
Studenții de anul 4 care refac disciplina pot veni și la examenul de sâmbătă, TODo 2018. Sesiunea de examene pentru anul 4 se încheie pe 9 iunie 2017. Studenții de anul 3 pot veni în alte zile față de cea aferentă grupei/seriei lor. Studenții în alte situații (de exemplu transferați de la IS) pot veni oricând. Cei care doresc să vină în altă zi față de cele alocate (inclusiv studenții de anul 4 care vor să vină sâmbătă, 3 iunie 2017), să trimită un e-mail către TODO cu subiectul [SO][Examen] Transfer: Prenume NUME, grupă
, de exemplu [SO][Examen] Transfer: Ana POPESCU, 332CB
.
Informații despre desfășurătorul și conținutul examenului găsiți în secțiunea aferentă din pagina de notare. În pregătirea examenului recomandăm să parcurgeți subiectele de examen anterioare.
Lucrări
Lucrare 1
La începutul cursului 4:
12 martie 2018, seria CA
14 martie 2018, seria CB
14 martie 2018, seria CC
3CA, varianta 1
Explicați diferența dintre descriptorii rezultați din două apeluri de open către acelasi fisier, și un apel de open urmat de un apel dup pe descriptorul rezultat.
Ce va afișa la rulare următorul cod, presupunând că fork este executat cu succes?
int i = fork();
if (i==0)
i = getppid();
else
sleep(1);
printf(“%d\n”, i);
Răspuns: La rularea codului se va afișa:
<pid-ul procesului părinte>
<pid-ul procesului copil>
Fork returnează 0 în cadrul procesului copil și pid-ul procesului copil în cadrul procesului părinte. Astfel, procesul copil va afla pid-ul procesului părinte și își va continua execuția prin printarea acestuia în timp ce procesul parinte face sleep de 1 secundă.
Scrieți secvența de cod care implementează comanda ls > /dev/null.
Răspuns:
pid_t pid = fork();
switch(pid) {
case 0:
fd = open(“/dev/null”, O_WRONLY | O_TRUNC | O_CREAT, 0644);
dup2(fd, STDOUT_FINENO);
close(fd);
execlp(“ls”, “ls”, NULL);
default:
waitpid(pid, NULL, 0);
}
De asemenea, au fost punctate și variantele care conțin variante în pseudocod ale apelurilor precum: open(”/dev/null”)
, exec(“ls”)
etc.
3CA, varianta 2
Dați un exemplu de funcție I/O care permite transmiterea de date către disk, rețea și dispozitive de tip caracter.
Ce va afișa la rulare următorul cod, presupunând că fork este executat cu succes?
int i = fork();
if (i==0)
i++;
else
sleep(1);
printf(“%d\n”, i);
Răspuns: La rularea codului se va afișa:
1
<pid-ul procesului copil>
Fork returnează 0 în cadrul procesului copil și pid-ul procesului copil în cadrul procesului părinte. Astfel, procesul copil va afla va incrementa variabila i, și o va afișa. Părintele va face sleep de 1 secundă și va afișa pid-ul procesului copil.
Scrieți secvența de cod care lansează în execuție ls | wc -l
.
Răspuns: O variantă de răspuns posibilă:
fd_redirect;
fd = fork();
if (fd == 0) { //child
close(STDOUT);
dup2(STDOUT, fd_redirect);
exec("ls");
} else if (fd > 0) { //parent
close(STDIN);
dup2(STDIN, fd_redirect);
wait(); //for child
exec("wc -l");
} else {
//error
}
3CB, varianta 1
Când este necesară execuția unui apel de sistem?
Cum ați implementa redirectarea pentru următoarea comandă bash ls >> test.out
(este de interes implementarea redirectării, în locul comenzii ls putea fi orice alta comandă)?
Răspuns: Variantă de răspuns:
int fd = open("test.out");
close (STDOUT_FILENO);
dup(fd);
close(fd);
lseek(STDOUT_FILENO,0, SEEK_END);
Câte procese se pot afla în starea RUNNING la un moment dat?
3CB, varianta 2
Indicați cel puțin un rol al nucleului (kernel-ului) într-un sistem de calcul.
Ce apeluri de sistem sunt necesare pentru a porni două procese care comunică prin intermediul unui pipe (ex ls | grep test
)?
Răspuns: O variantă de răspuns: Apelurile de sistem necesare pentru a porni două procese care comunică prin intermediul unui pipe sunt fork()
pentru crearea celor două procese, pipe()
pentru deschiderea unor pipe-urilor folosite de cele două procese, close()
pentru închiderea unuia din capetele pipe-urilor create înainte, dup2()
pentru redirectarea capetelor pipe-ului și execve()
pentru execuție.
Care este cauza principală pentru care un proces este în starea WAITING?
3CC, varianta 1
Stiva de rețea a unui sistem de operare poate fi implementată în user space sau în kernel space. De ce se preferă implementarea în kernel space?
Dați un exemplu de apel de bibliotecă/sistem, altul decât open()/fopen()
care duce la ocuparea unei intrări din tabela de descriptori de fișier a unui proces.
Răspuns: Popularea unei intrări în tabela de file descriptori se poate face cu apelul dup()
(sau dup2()
) pentru duplicarea unei intrări existente sau cu apeluri precum socket()
sau pipe()
pentru crearea unui socket sau a unui pipe care ocupă, respectiv, o intrare și două intrări.
Un proces execută apelul getppid()
în două situații diferite. În prima situație apelul întoarce valoarea 2832, iar în a doua situație apelul întoarce valoarea 1. Cum explicați?
3CC, varianta 2
Oferiți un motiv pentru care este necesară existența modului privilegiat (supervisor/kernel mode) într-un sistem de calcul.
Răspuns: Este nevoie de modul privilegiat pentru a asigura integritatea sistemului, izolarea între procese și accesul mediat la resurse. În absența modului privilegiat (kernel/supervisor mode), un proces ar putea scrie în memoria altui proces, ar putea corupe resurse sau ar putea citi informații de la resursele I/O fără să știe dacă sunt ale sale sau alte altcuiva.
Care este un avantaj și un dezavantaj al folosirii apelului printf()
în locul apelului write()
pentru afișarea unui mesaj la ieșirea standard a unui proces?
Răspuns: Avantajele folosirii printf()
sunt: formatare, portabilitate, mai puține apeluri de sistem (când mesajul este buffered). Dezavantaje: buffer-ul ocupă memorie, nu se afișează instant mesajul (este buffered).
Unui proces îi expiră cuanta de rulare (time slice) în momentul în care rulează pe un procesor (se află în starea RUNNING). Ce se întâmplă cu procesul?
Răspuns: La expirarea cuantei de timp, un proces este mutat din starea RUNNING în starea READY, unde va rămâne până va fi din nou planificat: adică până atunci când va primi o altă cuantă de rulare și va fi lăsat să ruleze pe procesor.
Greșeli frecvente
Lucrări foarte bune
Lucrare 2
La începutul cursului 7:
2 aprilie 2018, seria CA
4 aprilie 2018, seria CB
4 aprilie 2018, seria CC
3CA, varianta 1
Presupunând un sistem cu timp de access la RAM de 100ns, și știind că un context conține zece valori ale regiștrilor, estimați timpul necesar pentru o schimbare de context.
Un proces execută următorul cod:
for (i=0; i<100000; i++)
if (fork() == 0)
exit(1);
Care este consumul total de memorie fizică folosită de toate procesele copil în plus față de procesul părinte, exceptând structurile de date din kernel?
Răspuns: Variantă răspuns: Fiecare proces copil va aloca o pagină pentru stivă prin mecanismul copy-on-write (care va fi scrisă atunci când funcția exit își inițializează stack-frame-ul, salvând base pointer). Consumul total va fi 400MB. Variantă de răspuns acceptată: nu se va aloca nici o pagină în copil din cauza copy-on-write, pentru că nu se modifică nici o variabilă.
Dați un exemplu de algoritm de înlocuire de pagini pentru care creșterea memoriei fizice nu garantează reducerea numărului de major page faults.
3CA, varianta 2
Într-un sistem preemptiv cu planificator round-robin, explicați dacă este posibil ca două procese ce sunt planificate alternativ pe același procesor să primească timp de procesor diferit.
Dați un exemplu de situație în care unei pagini din procesul părinte nu i se aplică mecanismul copy-on-write după apelul fork()
, deși pagina respectivă este scrisă atât de copil cât și de părinte.
Dați avantaj și un dezavantaj al memory-mapped IO comparativ cu standard I/O.
Răspuns: Memory mapped I/O este mult mai rapid în general pentru că nu implică syscalls la fiecare acces; deasemenea mecanismul de paging nu încarcă în memorie decât paginile efectiv accesate. Orice eroare de I/O, de exemplu disk removed, este transmisă procesului prin semnale de genul SIGSEGV sau SIGBUF - iar programele trebuie să prindă și să trateze aceste semnale explicit. În cazul standard IO tratarea astfel de erori e mult mai simplă (-1, look at errno).
3CB, varianta 1
Într-un sistem doar cu procese I/O intensive, cuanta de rulare pe procesor ar trebui să fie mai mică sau mai mare decât în mod obișnuit pentru a eficientiza per ansamblu sistemul? Explicați.
Câte operații sunt necesare într-o arhitectură load/store pentru a copia o valoare între 2 locații de memorie RAM?
Alocăm un spațiu contiguu de 128MB folosind apelul mmap. Presupunând că dimensiunea paginii este de 4K, care este numărul maxim de page-fault-uri ce vor putea fi generate?
3CB, varianta 2
Într-un sistem doar cu procese CPU intensive, cuanta de rulare pe procesor ar trebui să fie mai mică sau mai mare decât în mod obișnuit pentru a eficientiza per ansamblu sistemul? Explicați.
Răspuns: Cuanta de rulare trebuie să fie mai mare întrucât la un context switch se pierde o perioadă importantă de timp, iar dacă cuanta ar fi prea mică, mai mult am sta în schimbarea de context decât să procesăm volumul mare de date pe procesor.
Precizați un avantaj și un dezavantaj al paginării.
Răspuns: Avantaje: memoria ocupată per proces, un proces are acces la tot spațiul virtual de memorie propriu, etc; Dezavantaje: mai multe accese la memoria fizică, prezența hardware-ului specializat (MMU, TLB), etc
Precizați 2 cazuri care generează un page fault atunci când accesăm o adresă validă de memorie.
3CC, varianta 1
De ce este important ca prioritățile proceselor să fie dinamice, nu statice, în contextul planificării proceselor?
Răspuns: Dacă prioritățile sunt statice, atunci procesele prioritare vor rula întotdeauna în fața celor mai puțin prioritare. Dacă sunt CPU bound, atunci acestea vor ocupa foarte mult procesorul și procesele mai puțin prioritare vor avea puțin timp să ruleze, ducând la starvation.
La ce este folosit PTBR (Page Table Base Register)? De ce sistemul nu ar putea funcționa fără un PTBR?
Apelul de mai jos este efectuat cu succes. În ce situație duce apelul la două page fault-uri?
memset(a, 0, 8); /* fill a with 8 bytes of 0 */
Răspuns: Scrisul de 8 octeți poate genera două page fault-uri atunci când sunt “atinse” două pagini de memorie care fie sunt în demand paging fie swappate. Dacă avem, de exemplu, 4 octeți pe o pagină (la sfârșit) și 4 octeți în pagina următoare (la început) vor rezulta două page fault-uri.
3CC, varianta 2
De ce procesele I/O bound primesc, în general, o cuantă de timp de rulare mai mare?
Răspuns: Procesele I/O bound sunt procese care se blochează des (și generează schimbări de context voluntare). Le alocăm o cuantă de timp mai mare pentru că nu vor apuca să o consume, se vor bloca. La următoarea planificare va consuma din restul de cuantă. Un proces CPU bound primește o cuantă mai mică pentru a fi forțat să iasă de pe proces (schimbare de context nevoluntară) atunci când îi expiră cuanta.
De ce este utilă prezența unei zone dedicate pentru kernel în spațiul virtual de adrese al fiecărui proces, față de un spațiu virtual de adrese dedicat pentru kernel?
Răspuns: La un apel de sistem se schimbă nivelul de privilegiu al procesorului dar nu se schimbă tabela de pagini, pentru că nu se schimbă spațiul de adresă. În felul acesta nu mai facem flush la TLB și avem overhead mai redus. În cazul în care kernel-ul ar avea un spațiu virtual de adrese propriu ar trebui făcută schimbarea tabelei de pagini (și flush la TLB).
De ce zona de text/cod a bibliotecii standard C poate fi partajată între mai multe procese, dar nu și zona de date?
Răspuns: Zona text este o zona read-only, pe când zona de date e modificabilă. Întrucât modificările trebuie să fie vizibile doar la nivelul procesului curent, zona de date e unică per proces (și nepartajate). Zona text nu se modifică și poate fi partajată de mai multe procese.
Greșeli frecvente
Lucrări foarte bune
Lucrare 3
7 mai 2018, seria CA
9 mai 2018, seria CB
9 mai 2018, seria CC
3CA, varianta 1
3CA, varianta 2
3CB, varianta 1
3CB, varianta 2
3CC, varianta 1
3CC, varianta 2
Greșeli frecvente
Lucrări foarte bune
Lucrare 4
3CA, varianta 1
3CA, varianta 2
3CB, varianta 1
3CB, varianta 2
3CC, varianta 1
3CC, varianta 2
Greșeli frecvente
Lucrări foarte bune
Examene anterioare