Examen CA/CB/CC 2017-2018
Examen final
Puteți participa la un singur examen final.
Datele de examen de SO pentru sesiunea iunie 2018 sunt:
joi, 31 mai 2018, ora 14:00, sala PR001 (studenți care refac materia)
joi, 7 iunie 2018, ora 14:00, sala EC105 (331CA, 332CA, 333CA, 334CA, 335CA) și sala EC004 (336CA, studenți care repetă/refac materia)
marți, 12 iunie 2018, ora 08:00, sala PR001 (331CB, 332CB, 333CB, 334CB, 335CB)
marți, 12 iunie 2018, ora 11:00, sala PR001 (331CC, 332CC, 333CC, 334CC, 335CC), sala EC004 (336CC, 336CB)
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.
Foi de examen
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
Implementați o incrementare atomică a variabilei t folosind funcția atomică GCC _sync_bool_compare_and_swap (int* t, int r, int n)
.
Răspuns:
do {
int s = t+1;
} while (!_sync_bool_compare_and_swap(&t,s-1,s));
Explicați cum poate un thread din procesul P1 citi memoria procesului P2.
Un atacator dorește să atace un sistem cu stack canary protection pe 8 octeți. Serverul care este atacat face 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?
Răspuns: Atacatorul poate exploata faptul ca valoarea canary ramane aceeasi intre doua conexiuni ale sale (din cauza fork). El poate ataca fiecare octet din canar independent, incepand cu primul; daca greseste o sa i se inchida conexiunea; daca nu, o sa mearga. Astfel, in medie va avea 128 de incercari (i.e. conexiuni) per octet. Dupa ce gaseste primul octet il ataca pe al doilea. In total va avea nevoie de 8 * 128 = 1024 incercari in medie.
3CA, varianta 2
Implementați un spinlock folosind funcția atomică GCC _sync_bool_compare_and_swap (int* t, int r, int n)
.
Răspuns:
while (!_sync_bool_compare_and_swap(&lock,0,1));
Explicați de ce este mai ieftină crearea unui thread comparativ cu crearea unui proces nou.
De câte încercări are un atacator nevoie (în medie) pentru a găsi o adresă de cod validă pe un sistem de 64 biti atunci când atacă un sistem cu ASLR pornit. Acest sistem rulează un server care face fork() pentru fiecare client și care are un stack overflow exploatabil de client prin modificarea inputului.
3CB, varianta 1
Care e motivul pentru care secțiunile .data
și .bss
sunt separat puse în fișierul executabil?
Se crează 2 thread-uri în cadrul aceluiași proces. Se poate ca unul din thread-uri să modifice fluxul executiei celuilalt thread?
Secventa de cod a += 5
este atomică? (la executarea secvenței de 2 thread-uri, rezultatul final va fi același tot timpul) Explicați.
3CB, varianta 2
Care este motivul pentru care secțiunea de cod este stocată separat de restul datelor într-o zonă denumită .text
?
Cum putem preveni un atac de tip stack buffer overflow?
De ce nu este atomică instrucțiunea add [%rax], 5
cand avem 2 core-uri în sistem?
3CC, varianta 1
De ce trecerea peste limita unui buffer (buffer overflow) nu generează, de obicei, excepție de acces la memorie (de tipul Segmentation fault)?
Răspuns: Întrucât sistemul de operare gestionează memoria la nivel de pagini. Un buffer este o parte a unei pagini. Dacă trecerea peste limita unui buffer (buffer overflow) nu duce la trecerea într-o altă pagină (nevalidă), atunci nu rezultă în excepție de acces la memorie, accesul fiind valid din punctul de vedere al sistemului de operare.
De ce schimbarea de context între două thread-uri user-level este mai rapidă decât schimbarea de context între două thread-uri kernel-level ale aceluiași proces?
Răspuns: Thread-urile cu implementare kernel-level fac schimbarea de context la nivelul nucleului sistemului de operare, lucru care presupune schimbarea nivelului de privilegiu din user space în kernel space și invocarea planificatorului. Thread-urile cu implementare user-level fac schimbarea de context în user space, fără apel de sistem sau tranziție în kernel space (cauzatoare de overhead) și este așadar mai rapidă.
De ce instrucțiunea a++
din C poate fi atomică pe un sistem x86 single-core dar niciodată pe un sistem x86 multi-core?
Răspuns: Instrucțiunea a++ se poate traduce în add [mem_address], 1. O astfel de instrucțiune este atomică pe un singur core (nu poate fi întreruptă în mijlocul execuției). Însă, pe un sistem multi-core, instrucțiunea se “desface” în acțiuni de load, add, store și lucru cu magistrala de acces la memorie, magistrală partajată. Pe un astfel de sistem multi core, pot exista întrețeseri de acces la magistrală din parte mai multor core-uri care fac instrucțiunea neatomică și duc la rezultate nedeterministe.
3CC, varianta 2
Pentru a putea folosi un shellcode pe un sistem care are suport DEP (Data Execution Prevention) un atacator folosește apelul mprotect()
. De ce și cum folosește atacatorul apelul mprotect()
?
Răspuns: Un sistem cu suport DEP va marca zonele writable din spațiul virtual de adrese al unui proces (data, bss, stack, heap) ca neexecutabile. Un shellcode este injectat într-o zonă writable. Pentru a putea fi executat trebuie ca acea zonă să fie executabilă. Pentru aceasta folosim apelul mprotect() care adaugă permisiuni de execuție (PROT_EXEC) acelei zone în care am injectat shellcode-ul.
De ce schimbarea de context între două thread-uri ale aceluiași proces e mai rapidă decât schimbarea de context între două procese?
Răspuns: Schimbarea de context între două thread-uri ale aceluiași proces nu schimbă spațiul virtual de adrese, deci nu schimbă tabela de pagini, care duce la anularea intrărilor din TLB. Schimbarea de context între două thread-uri din procese diferite duce la schimbarea spațiului virtual de adrese, lucru care înseamnă schimbarea tabelei de pagini și are overhead suplimentar.
Cum arată în pseudo-asamblare implementarea primitivei lock()
pentru un spinlock?
Răspuns: Un spinlock este o variabilă care este actualizată atomic. Operația lock() pe spinlock este un busy waiting cât timp acea variabilă este ocupată, adică cineva a achiziționat deja spinlock-ul. Această verificare trebuie să fie atomică, lucru realizat cu operații atomice de tipul CAS (compare-and-exchange) și lock pe magistrală. Dacă valoarea 1 înseamnă spinlock liber, iar 0 spinlock ocupat, în pseudo-asamblare implementarea operației lock() va fi:
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
Greșeli frecvente
Buffer Overflow (scrierea peste dimensiunea buffer-ului) este considerat a fi același lucru cu atacul de tip Stack Buffer Overflow.
Buffer Overflow (trecerea peste dimesiunea unui buffer) se întâmplă doar pe stivă. Un buffer overflow poate să apară și pe heap.
Codul este pus într-o zonă diferită față de celelalte date pentru a evita suprascrierea de cod. Nu se explică faptul că diferă permisiunile, presupun că fac un buffer overflow până în cod.
Pentru a preveni atacuri de tip stack buffer overflow se folosesc ASLR și DEP. ASLR și DEP sunt folosite pentru a îngreuna anumite atacuri, nu pentru a preveni buffer overflow-ul în sine. DEP previne execuția unui shellcode introdus de atacator deoarece zona respectivă nu are concomitent permisiuni de write și execute. Singura legătură cu buffer overflow-ul e că suprascriind adresa de retur a funcției să pointeze către shellcode, acesta nu va putea fi executat. ASLR pune adresele funcțiilor din libc random pentru a îngreuna apelul unor funcții de bibliotecă precum system. Însă, folosind return-to-libc (prin exploatarea unui buffer overflow), se pot leak-ui adresele funcțiilor din libc și se poate calcula offset-ul funcțiilor dorite, făcându-se bypass ASLR-ului. Astfel, ASLR nu previne buffer overflow-ul.
Lucrări foarte bune
Lucrare 4
3CA, varianta 1
Explicați pașii necesari pentru a transfera un bloc de la un HDD către aplicația care citește un fișier.
Răspuns: Pas 1. Driver-ul SO programează controller-ul de hard-disc să citească blocul.
Pas 2. HDD-ul citește blocul, plasând conținutul într-un buffer intern al HDD;
Pas 3. controller inițiază DMA pentru a transfera datele în memorie;
Pas 4. când DMA se finalizează, se generează o întrerupere pentru a anunța procesorul că datele sunt disponibile.
La momentul t0 apelul send întoarce valoarea 100. Presupunând că apelurile pe sockeți sunt blocante, este posibil ca apelul recv
efectuat la celălalt capăt al conexiunii la momentul t1 > t0 să întoarcă valoarea -1?
Dorim să folosim un sistem de fișiere FAT pentru un disc de 10TB și dimensiunea blocului de 4KB. Cât de mare va fi tabela FAT pentru acest disc?
3CA, varianta 2
Dați un exemplu în care polling este preferabil în defavoarea întreruperilor pentru lucrul cu dispozitive I/O.
Răspuns: La plăcile de rețea cu viteză mare (10Gbps sau mai mult), când vin pachete mici (e.g. 64B) se vor genera milioane de întreruperi pe secundă, și fiecare întrerupere este costisitoare (salvare context, etc). Dacă folosim polling, evităm acest cost și performanța este mai bună.
Atunci când se transmit 10.000 octeți folosind un socket TCP, de câte apeluri recv(fd, buf, 10000, 0)
va nevoie pentru a primi toate datele?
Pe un HDD cu capacitate de 1TB dorim să instalăm un sistem de fișiere ext2 cu dimensiunea blocului de 4KB. Câte nivele de indirectare sunt necesare pentru a permite unui fișier să ocupe (aproape) tot spațiul de pe HDD?
3CB, varianta 1
În directorul curent există fișierul in.dat. Executăm comanda /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?
Executăm linia următoare 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.
Creăm un hardlink la un fișier. Dacă ștergem acel fișier, link-ul devine invalid? Explicați mecanismul din spate.
3CB, varianta 2
Dorim să modificăm setările unui driver în Linux. Ce apel de sistem folosim pentru acest lucru?
Executăm linia următoare 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.
Gestiunea spațiului liber într-un sistem de fișiere se face folosind o structura de tipul vector de biți sau o listă înlănțuită. Precizați câte un dezavantaj al fiecărei metode.
3CC, varianta 1
Un program rulează prima dată într-un sistem, apoi este oprit. Apoi este pornit din nou. Se observă că timpul de pornire a doua oară este mult mai mic. Care este explicația?
Răspuns: Când pornește prima oară, secțiunile din fișierul executabil al programului/procesului sunt aduse prima oară în RAM de pe disc (suportul persistent), acțiune care durează. După ce procesul este oprit, mare parte din secțiuni rămân în buffer cache, astfel că a doua oară nu mai este nevoie de aducerea lor de pe disc, iar pornirea e mai rapidă.
În ce situație se blochează un apel send()
pe un socket?
Ce conțin blocurile de date ale unui director?
3CC, varianta 2
Care este o diferență între o operație non-blocantă și o operație asincronă?
Răspuns: Operațiile non-blocante sunt operații care nu blochează execuția procesului, întorcându-se imediat; operațiile non-blocante fie întorc datele disponibile atunci (sincron), fie declanșează în spate execuția unei operații (asincron). Operațiile asincrone sunt operații care se execută separat de fluxul de execuție al procesului (asincron); rezultatul acestor operației este disponibil la încheierea operației prin notificarea procesului sau dacă procesul interoghează starea operației. În general operațiile asincrone sunt non-blocante.
În ce situație se blochează un apel recv()
pe un socket?
Cu ce diferă un hard link de un symbolic link?
Greșeli frecvente
Funcția recv() se blochează atunci când buffer-ul e plin.
Operatiile non-blocante sunt doar cele de genul pe fișiere cu flag-ul O_NONBLOCK - dau datele imediat. Practic a fost făcută o comparație între O_NONBLOCK
si ASYNC IO
.
Operațiile non-blocante nu notifică procesul, iar operațiile asincrone notifică procesul.
Lucrări foarte bune
Examene anterioare