Urmăriți precizările din pagina de reguli.
Puteți participa la un singur examen final.
Datele de examen de SO pentru sesiunea iunie 2019 sunt:
Datele de examen de SO pentru sesiunea septembrie 2019 sunt:
Puteți veni o singură dată la examen. Studenții care refac materia pot veni doar în primele două date de examen (TODO și TODO). Pentru ei sesiunea este mai scurtă (TODO - TODO).
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, să trimită un e-mail către Elena 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.
Urmăriți precizările din pagina de reguli.
[SO][Lucrare X] Transfer Prenume Nume, Grupa
unde:X
este indexul lucrării (1, 2, 3 sau 4)Prenume
este prenumele.Nume
este numa.Grupa
este grupa.[SO][Lucrare X] Prenume NUME - grupa
; de exemplu [SO][Lucrare 1] Andreea POPESCU - 332CA
.printf(”aici”)
înainte de o instrucţiune care accesează o zonă de memorie invalidă nu afişează nimic la consolă.int i = 0; if (fork()==0) i++; else sleep(1); printf(”%d\n”,i);
fwrite(..)
este mai rapid decât write(..)
atunci când facem multe scrieri.int i = 0; for (i = 0;i<5;i++) if (fork()>0) break;
int fd2 = dup(fd)
. Execuția apelului de sistem write
pe fd2 va influența în vreun fel apelurile ce folosesc ca parametru fd? Explicați.int fd2 = dup(fd)
. Execuția apelului de sistem write
pe fd va influența în vreun fel apelurile ce folosesc ca parametru fd2? Explicați.fwrite()
în loc de write()
.close(fd)
executat cu succes. Observăm că structura de fișier deschis referită de descriptorul fd (acum închis) nu este eliberată din memorie. De ce?close(fd)
invalidează descriptorul fd și decrementează contorul de referință din structura de fișier deschis. Structura este dezalocată în momentul în care contorul de referință este 0. Dacă după close(fd)
structura de fișier deschis nu a fost dezalocată înseamnă că mai există un descriptor care o referă, descriptor care a fost obținut printr-un apel dup()
sau dup2()
. Un apel open()
nu este un răspuns corect, pentru că acela creează o structură nouă de fișier deschis.write()
? Argumentați răspunsul.write()
modifică pointer-ul/cursorul de fișier, îl crește cu numărul de octeți scriși în fișier; cursorul de fișier este reținut în structura de fișier deschis. În plus, dacă în urma scrierii octeților se trece de limita fișierului, atunci se modifică și dimensiunea fișierului; dimensiunea fișierului este reținută în structura de fișier de pe disc (FCB).&
în shell?&
în shell, shell-ul nu mai așteaptă încheierea procesului nou creat. Adică shell-ul nu apelează wait() și nu se blochează în așteptarea încheierii execuției procesului. Din acest motiv shell-ul poate primi noi comenzi de la terminal.&
în shell. În shell, &
are rolul de a duce un proces în background, nu de a face o dereferențiere (ca de exemplu în C) sau de operator logic AND între comenzi (precum &&
).stdin
, stdout
și stderr
.a) a = mmap(...., n * 1024 * sizeof(int),....); for(i = 0; i < n * 1024; i = i + 1024) a[i] = i; b) b = mmap(...., n * 1024 * sizeof(int),....); for(j = 0; j < n; j++) b[j] = j;
Care dintre secvențe este mai rapidă și de ce?
*a = 3;
În ce situație executarea acestei instrucțiuni va conduce la evacuarea unei pagini în spațiul de swap (swap out)?*a = 3
înseamnă un acces la memorie în pagina virtuală ce conține adresa indicată de pointerul a. Dacă acea pagină virtuală nu are pagina fizică rezidentă (adică în memoria fizică / RAM), pagina fizică nu a fost alocată încă (demand paging) sau se găsește pe spațiul de swap sau a apărut duplicarea ei ca urmare a copy-on-write. Dacă nu aveam nici o pagină disponibilă, atunci este nevoie de evacuarea unei pagini (swap out) și folosirea paginii eliberate.sem == 0
) folosind suportul hardware oferit de funcția compare_and_swap (cas): int compare_and_swap(int* reg, int oldval, int newval);
int sem = 0; void up(){ while (1) { int o = sem; if (cas(&sem, o, o+1)) break; } } void down() { while (1) { int o; while ((o = sem) == 0); if (cas(&sem, o, o-1)) break; } }
fork()
, și va apela o funcție de tratare a cererii.
int compare_and_swap(int* reg, int oldval, int newval);
void unlock(){ lock = 0; } void lock() { while (!cas(&lock,0,1)); }
int a=10, b = 10000; // variabile globale thread_func() { a--; if ( a > 0) { b += b / a; } }
La un moment dat, execuția programului este întreruptă de o eroare. Identificați/explicați problema și propuneți o soluție.
-fstack-protector
. Implementarea se bazează pe un pool de procese care va deservi clienții. Workerii sunt creați printr-un apel fork()
, urmat de un apel execve()
ce va încărca un binar (compilat la fel ca serverul) care tratează cererile clienților. Când un worker moare, altul va fi creat în locul său. Funcția de prelucrare a cererilor conține următoarele 2 linii: char a[10]; read(socket, a, 100);
Poate fi acesta exploatat printr-un atac de tipul buffer overflow? Motivați
a = a + 5
nu este atomică.cmpxchg
pe x86 ) pentru implementarea unui spinlock pe sistemele multicore?execve()
.a.txt
după această operație?/proc/interrupts
?/proc/interrupts
. Ne uităm pe ultima coloană (coloana cu modulele de kernel atașate), și căutăm linia unde apare modulul care corespunde plăcii noastre de rețea (e.g. ath9k (WI-FI atheros) sau en*
(ethernet)). Pe coloanele CPU0-CPU3 găsim numărul de întreruperi declanșate pe fiecare nucleu.connect()
pe un socket TCP de tip listener se creează un nou socket TCP de tip conexiune care este folosit pentru comunicare. Ambii sockeți (și alții sockeți creați cu apelul connect()
) au aceeași adresă IP și port. Cum demultipleaxează sistemul pachetele pentru a le livra socket-ului corespunzător?