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 2018 sunt:
Datele de examen de SO pentru sesiunea septembrie 2018 sunt:
Puteți veni o singură dată la examen. Studenții care refac materia pot veni doar în primele două date de examen (31 mai 2018 și 7 iunie 2018). Pentru ei sesiunea este mai scurtă (26 mai 2018 - 8 iunie 2018).
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.open() urmat de un apel dup() descriptorii vor indica spre aceeași structură.int i = fork(); if (i==0) i = getppid(); else sleep(1); printf(“%d\n”, i);
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.
int i = fork(); if (i==0) i++; else sleep(1); printf(“%d\n”, i);
ls | wc -l.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 }
ls >> test.out (este de interes implementarea redirectării, în locul comenzii ls putea fi orice alta comandă)? int fd = open("test.out");
close (STDOUT_FILENO);
dup(fd);
close(fd);
lseek(STDOUT_FILENO,0, SEEK_END);
ls | grep test)?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.open()/fopen() care duce la ocuparea unei intrări din tabela de descriptori de fișier a unui proces.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.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?getppid() întoarce pid-ul procesului părinte. În prima situație valoarea returnată este diferită de 1 deoarece procesul are un părinte (creator) care încă rulează. În cea de-a doua situație procesul a fost adoptat de init deoarece părintele creator al procesului și-a terminat execuția și nu l-a așteptat.printf() în locul apelului write() pentru afișarea unui mesaj la ieșirea standard a unui proces?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).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?
fork(), deși pagina respectivă este scrisă atât de copil cât și de părinte.mmap (…, MAP_SHARED,…);memset(a, 0, 8); /* fill a with 8 bytes of 0 */
_sync_bool_compare_and_swap (int* t, int r, int n).do {
int s = t+1;
} while (!_sync_bool_compare_and_swap(&t,s-1,s));
fork() pentru fiecare client și are un stack overflow exploatabil de client prin modificarea inputului. De câte încercări are nevoie atacatorul, în medie, pentru a ghici valoarea canary?_sync_bool_compare_and_swap (int* t, int r, int n).while (!_sync_bool_compare_and_swap(&lock,0,1));
.data și .bss sunt separat puse în fișierul executabil?.bss refera variabila globale care au valoarea 0. Gruparea acestora intr-o sectiune speciala, diferita de .data, optimizeaza consumul de spatiu intrucat nu mai este necesar sa stocam 0-uri.a += 5 este atomică? (la executarea secvenței de 2 thread-uri, rezultatul final va fi același tot timpul) Explicați..text?add [%rax], 5 cand avem 2 core-uri în sistem?a++ din C poate fi atomică pe un sistem x86 single-core dar niciodată pe un sistem x86 multi-core?mprotect(). De ce și cum folosește atacatorul apelul mprotect()?lock() pentru un spinlock?spinlock = 1; /* initial value is 1 - open */
lockfn:
lock cmpxchg spinlock, 1, 0
cmp old_value, 0 ; if old_value (stored in a register by cmpxchg) is 0, busy wait
je lockfn
recv efectuat la celălalt capăt al conexiunii la momentul t1 > t0 să întoarcă valoarea -1?recv(fd, buf, 10000, 0) va nevoie pentru a primi toate datele?/usr/bin/time -v cp in.dat out.dat. Aceasta durează 1 secundă. Mai executăm o dată comanda /usr/bin/time -v cp in.dat out.dat. A doua oară aceasta va dura doar 0.1 secunde. Care ar putea fi cauza?int n = recv(s,buf,1000,0);. Dați exemplu de un caz în care n va fi 1 și de un caz în care n va fi 1000.int n = send(s,buf,2000,0);. Dați exemplu de un caz în care n va fi 1 și de un caz în care n va fi 2000.send() pe un socket?recv() pe un socket?O_NONBLOCK si ASYNC IO.