# Fie procesul P1. Câte procese copil va avea P1 în urma rulării secvenței de pseudocod de mai jos? De ce?
while(fork() == 0) ;
#* Răspuns: Apelul fork} întoarce 0 în procesul copil și PID-ul procesului copil, diferit de 0, în părinte. De aceea, părintele va executa o singură dată fork}, ieșind apoi din buclă. Copilul va mai executa o dată bucla, devenind la rândul lui părinte și ieșind din buclă. Fiecare proces va fi părinte pentru un singur copil. Astfel, P1 va avea un singur proces copil. # De ce aduce un apel de sistem mai mult overhead decât un apel de funcție obișnuit? #* Răspuns: Un apel de sistem aduce mai mult overhead datorită comutării în kernel-space, în timp ce un apel de funcție se execută în user-space. # Unde este poziționat cursorul de fișier fd1} în urma secvenței de mai jos? Presupuneți că toate apelurile se întorc cu succes.
fd1 = open("a.txt", O_RDWR | O_CREAT | O_TRUNC, 0644); fd2 = open("a.txt", O_RDWR | O_CREAT | O_TRUNC, 0644); write(fd2, "1", 1); dup2(fd2, fd1);
#* Răspuns: În urma apelului open}, cursorul de fișier fd2} va poziționat la început. După write}, acesta va poziționat la 1 octet după începutul fișierului, iar după dup2}, și cursorul de fișier fd1} va poziționat la 1 octet după începutul fișierului.
# Fie secvența de pseudocod de mai jos:
fd1 = open("a.txt", O_RDWR | O_CREAT | O_TRUNC, 0644); pid = fork(); switch (pid) { case 0: break; default: dup(fd1); }
Presupunând că toate apelurile se întorc cu succes, câți descriptori din fiecare proces vor referi fișierului a.txt}? #* Răspuns: 3 descriptori; 2 descriptori în părinte (fd1} și descriptorul rezultat în urma dup}) și 1 descriptor în copil (fd1}, moștenit de copil în urma fork}). # Care este numărul minim de descriptori de fișier ai unui proces pot referi, la un moment dat, stderr} (standard error)? De ce? #* Răspuns: Numărul minim este 0, deoarece stderr} poate fi închis prin apel close}. # În ce zonă de memorie este plasată adresa de retur a unei funcții? De ce? #* Răspuns: Adresa de retur a unei funcții este plasată pe stivă. La fiecare apel de funcție, un nou stack frame este creat pe stivă, care conține parametrii funcției, adresa de retur și variabile locale. La ieșirea din funcție, adresa de retur este preluată de pe stivă.
# Fie secvența de pseudocod de mai jos:
fd1 = open("a.txt", O_RDONLY); fd2 = open("b.txt", O_RDWR); dup2(fd1, fd2); write(fd2, "X", 1);
Care sunt valorile posibile ce pot fi intoarse de apelul write}? #* Răspuns: # Dacă toate apelurile se întorc cu succes, în urma apelului dup2}, fd2} va puncta către a.txt} deschis o_rdonly}, iar apelul write} va întoarce -1 și va seta errno la valoarea ebadf}, pentru a semnala eroarea. # Dacă apelul dup2} eșuează, fd2} va puncta către b.txt} deschis o_rdwr}, iar apelul write} va întoarce 1, dacă a scris caracterul, sau 0, dacă nu a scris caracterul. # De ce apelul fopen} realizează în spate apel de sistem, dar apelul memcpy} nu? #* Răspuns: #* fopen} realizează apelul de sistem open} pentru a putea deschide/crea un fișier sau dispozitiv, pentru acest lucru fiind necesară trecerea în kernel-space. #* memcpy} nu realizează apel de sistem deoarece scrie și citește memorie deja alocată în spațiul de adresă al procesului fără a trece în kernel-space. # Dați două exemple în care: #* a) un proces are mai multe procese părinte decât procese copil; #* b) un proces are mai multe procese copil decât procese părinte. #* Răspuns: #* toate procesele, cu excepția procesului init}, au un proces părinte; # a) un proces care nu are procese copil (nu a executat fork} niciodată); # b) un proces care are cel puțin două procese copil (a executat fork} de cel puțin două ori, cu succes) sau procesul init} care nu are proces părinte.
# Fie un fișier a.txt} având dimensiunea de 1024 octeți și secvența de pseudocod de mai jos:
fd1 = open("a.txt", O_RDWR | O_TRUNC); close(fd1); fd1 = open("a.txt", O_RDWR | O_APPEND);
Unde va fi poziționat cursorul de fișier ale descriptorului fd1}? De ce? #* Răspuns: În urma primului apel open}, flag-ul o_trunc} reduce dimensiunea fișierului la 0. Al doilea apel open} poziționează cursorul la sfârșitul unui fișier gol, adică pe poziția 0. Dacă fișierul a.txt} nu există, toate apelurile vor întoarce -1. # De ce apelul fork} întoarce 0 pentru succes în procesul copil și o valoare diferită de 0 pentru succes în procesul părinte? #* Răspuns: În procesul copil întoarce 0 pentru că procesul poate folosi apelul getppid} pentru a afla PID-ul procesul părinte. În procesul părinte, fork} întoarce PID-ul procesului copil. Un proces poate avea mai multe procese copil și este comod ca fork} să întoarcă PID-ul procesului copil proaspăt creat. # Care dintre următoarele apeluri pot modifica numărul de procese dintr-un sistem UNIX: open}, fork}, dup2}, wait}, exec}? #* Răspuns: # open} deschide și, posibil, creează un nou fișier sau dispozitiv - NU # fork} creează un nou proces - DA # dup2} duplică un descriptor de fișier - NU # wait} așteaptă schimbarea stării unui proces, în cazul unui proces copil care și-a încheiat execuția, permite sistemului să elibereze resursele asociate cu copilul, ducând la scăderea numărului de procese din sistem - DA # exec} înlocuiește imaginea procesului curent cu o nouă imagine de proces - NU ==== Lucrare 2 ==== *27 martie, 09:05-09:15, EC004, seria CA *28 martie, 17:05-17:15, EC105, seria CC ==== 3CA, nr. 1 ==== # Dați exemplu de acțiune ce conduce la trecerea unui proces din starea running} în waiting} și un exemplu de acțiune care conduce la o trecere inversă. #* Răspuns # Un proces trece din starea running} în waiting} atunci când execută o acțiune blocantă. # Un proces nu poate trece direct din starea waiting} în running}. Procesul trece în starea ready} atunci când a dispărut cauza blocării sale. # Dați exemplu de avantaj, respectiv dezavantaj al sincronizării folosind semafoare binare în fața spinlock-urilor. #* Răspuns: # Avantaj: Deoarece semafoarele binare nu folosesc busy waiting, pot fi folosite pentru secțiuni critice de orice dimensiune. # Dezavantaj: Un proces va ceda procesorul dacă nu poate lua semaforul. Operația de down} are un overhead ridicat, datorită schimbării de context. # În ce mod influențează dimensiunea TLB-ului numărul maxim de spații de adresă existente în sistem? #* Răspuns: TLB-ul menține mapări de pagini fizice și pagini virtuale. Conține un subset al tabelei de pagini. Numărul maxim de spații de adresă existente în sistem depinde de numărul de procese existente în sistem. Acest număr nu este influențat de dimensiunea TLB-ului. ==== 3CA, nr. 2 ==== # Cum ar trebui aleasă cuanta de timp pentru procese pentru un sistem în care se dorește interactivitate mare? De ce? #* Răspuns: Cuanta de timp trebuie să fie mică pentru ca procesele să fie preemptate mai des și să crească timpul de răspuns al sistemului. # Dați exemplu de avantaj, respectiv dezavantaj al sincronizării folosind spinlock-uri în fața mutex-urilor. #* Răspuns: # Avantaj: Un proces nu va ceda procesorul dacă nu poate lua spinlock-ul. Operația de lock} are un overhead scăzut. # Dezavantaj: Deoarece spinlock-urile folosesc busy waiting, sunt recomandate doar pentru secțiuni critice mici, ce se execută rapid. # Fie un utilizator fără drepturi de administrator. În ce mod poate acesta modifica numărul de pagini fizice din sistem? Dar numărul de pagini virtuale? #* Răspuns: # Numărul de pagini fizice din sistem poate fi modificat prin adăugarea/scoaterea de memorie fizică din sistem sau prin modificarea dimensiunii paginilor fizice, având suport hardware. Pentru aceste operații este necesar un administrator, deci un utilizator fără drepturi de administrator nu poate modifica numărul de pagini fizice din sistem. # Un utilizator fără drepturi de administrator poate modifica numărul de pagini virtuale din sistem prin crearea/omorârea de procese, deoarece fiecare proces ale paginile virtuale proprii. ==== 3CC, nr. 1 ==== # În ce mod este determinat numărul de procese care se pot afla, la un moment dat, în starea running} de următoarele componente fizice ale sistemului: număr de procesoare, arhitectură pe 32/64 biți, memorie fizică, capacitate de stocare? #* Răspuns: Numărul de procese care se pot afla, la un moment dat, în starea running} depinde doar de numărul de procesoare, deoarece pot exista maxim n procese în starea running} pe un sistem cu n procesoare. Celelalte componente nu influențează acest număr. # Care metodă de sincronizare (mutex sau spinlock) este mai avantajoasă pentru sincronizarea accesului la următoarea regiune critică și de ce? Prezentați cel puțin un motiv.<code c>… start regiune critica c=a+b; a=b; b=c; stop regiune critica …</code> #* Răspuns: Deoarece regiunea critică este mică, este mai avantajoasă folosirea unui spinlock pentru sincronizare, deoarece se evită overhead-ul unei schimbări de context. # Dați exemplu de avantaj, respectiv dezavantaj al paginării simple (neierarhice) în fața paginării ierarhice. #* Răspuns: # Avantaje: #* Overhead de prelucrare mic (este parcursă o singură tabelă de pagini); #* Complexitate mică de implementare. # Dezavantaj: paginarea simplă ocupă mai mult spațiu, deoarece se ocupă spațiu și pentru zonele de memorie virtuale nevalide. ==== 3CC, nr. 2 ==== # În ce mod este determinat numărul de procese care se pot afla, la un moment dat, în starea ready} de următoarele componente fizice ale sistemului: număr de procesoare, arhitectură pe 32/64 biți, memorie fizică, capacitate de stocare? #* Răspuns: Numărul de procese care se pot afla, la un moment dat, în starea ready} depinde de memoria fizică, deoarece coada/cozile ready} sunt reținute în liste în memoria fizică, iar dimensiunea acesteia poate limita dimensiunile acestora. Celelalte componente nu influențează, în general, acest număr. # Observație: Au fost considerate valide următoarele argumente: #* pentru dimensiuni mari ale memoriei fizice (peste 4 GB) este relevantă arhitectura, pentru a putea adresa memoria disponibilă; #* existența mai multor procesoare duce la creșterea numărului de procese aflate simultan în starea running}, astfel că scade numărul de procese care ar fi fost în starea ready}, diferența fiind egală cu diferența dintre numărul de procesoare; # Care dintre următoarele operații pot genera schimbare de context cu o cauză diferită de expirarea cuantei? De ce? lock_mutex}, unlock_mutex}, spin_lock_spinlock}, spin_unlock_spinlock}, down_semaphore}, up_semaphore}. #* Răspuns: # lock_mutex} - încercarea de a obține un mutex inaccesibil trece procesul în starea waiting} - DA # unlock_mutex} - la ieșirea din zona critică, procesele care așteptau la mutex vor trece din starea waiting} în starea ready} - DA # spin_lock_spinlock} - încercarea de a obține un spinlock inaccesibil nu trece procesul în starea waiting} - NU # spin_unlock_spinlock} - la ieșirea din zona critică, procesul care aștepta la spinlock se va debloca, dar va rămâne în starea running} - NU # down_semaphore} - încercarea de a obține un semafor inaccesibil trece procesul în starea waiting} - DA # up_semaphore} - la ieșirea din zona critică, procesele care așteptau la semafor vor trece din starea waiting} în starea ready} - DA # Dați exemplu de avantaj, respectiv dezavantaj al folosirii TLB. #* Răspuns: # Avantaj: TLB-ul este un cache rapid care menține mapări de pagini fizice și pagini virtuale. În cazul TLB hit, scade timpul de acces la memorie. # Dezavantaje: #* În cazul TLB miss, timpul de acces la memorie este mai mare decât timpul de acces în absența TLB-ului. #* La fiecare schimbare de context se face TLB flush, astfel că vor exista mai multe miss-uri imediat după schimbarea de context. #* Dimensiune mică și cost ridicat. ==== Lucrare 3 ==== *24 aprilie, 09:05-09:15, EC004, seria CA *25 aprilie, 17:05-17:15, EC105, seria CC ==== 3CA, nr. 1 ==== # Motivați utilizarea copy-on-write în cadrul apelului fork}. #* Răspuns: Este utilă folosirea mecanismului de copy-on-write deoarece crearea unui nou proces se face mai rapid, evitând operațiile de copiere a memoriei. Foarte probabil, după fork} copilul va face un apel exec} pentru a lansa un program diferit. Astfel, dacă nu s-ar folosi copy-on-write, s-ar copia degeaba paginile din spațiul de adresă al părintelui. # Dați 2 exemple de resurse partajate între thread-urile aceluiași proces. #* Răspuns: Thread-urile aceluiași proces partajează descriptorii de fișier, spațiul de adrese (memoria), masca de semnale, deoarece acestea sunt resurse la nivel de proces, nu de thread. ##* Ele folosesc aceleași segmente de memorie heap}, data} și bss}. (deci și variabilele stocate în ele) # Fie un program multithreaded cu user-level threads care efectuează multe operații I/O per thread. Este mai eficientă folosirea operațiilor I/O blocante sau non-blocante? #* Răspuns: Efectuarea unei operații blocante în cadrul unei implementări cu user-level threads va bloca întreg procesul, nu doar thread-ul curent. De aceea este mai eficientă folosirea operațiilor I/O non-blocante. ==== 3CA, nr. 2 ==== # Prezentați un avantaj și un dezavantaj al mapării fișierelor în memorie. #* Răspuns: ##* Avantaje: ###* Se evită apelurile de sistem read} și write}, deci și double-buffering-ul. ###* Permite partajarea fișierelor între procese. ###* Nu mai este necesar apelul lseek}, căutarea se realizează prin manipularea pointer-ilor. ##* Dezavantaje: ###* Maparea fișierelor în memorie se face la nivel de pagină, astfel că apare fragmentare, mai ales în cazul fișierelor mici. ###* Maparea trebuie să se încadreze în spațiul de adresă al procesului. Pe sisteme pe 32 de biți, sunt dificil de mapat fișiere mari. ###* Accesul la memorie determină apariția page fault-urilor. ###* Trebuie apelat periodic msync}, deoarece modificările în memorie nu sunt scrise imediat pe disc. # Dați 2 exemple de resurse care NU sunt partajate între thread-urile aceluiași proces. #* Răspuns: Fiecare thread al unui proces are un context de execuție propriu, format din stivă și set de regiștri (deci și un contor de program - registrul (E)IP). De asemenea, TLS/TSD reprezintă variabile specifice unui thread, invizibile pentru celelalte thread-uri. # Fie afirmația “Întreruperile pot fi folosite la fel de bine și pentru dispozitive care folosesc memory-mapped I/O și pe sisteme care folosesc port-mapped I/O”. Precizați și justificați valoarea de adevăr a afirmației. #* Răspuns: Întreruperile sunt semnale folosite de către dispozitive pentru a semnala procesorului finalizarea unei operații de I/O. Acesta va salva starea curentă și va rula rutina de tratare a întreruperii. Utilizarea memory-mapped I/O sau a port-mapped I/O determină doar modul de adresare a dispozitivelor în cadrul rutinei de tratare, fără a afecta eficiența utilizării întreruperilor. Astfel, afirmația este adevărată. ==== 3CC, nr. 1 ==== # În ce situație folosirea funcției memcpy} generează page fault și în ce situație nu generează page fault? #* Răspuns: Funcția memcpy} folosește două buffere: sursă și destinație. Fie s} mulțimea paginilor în care se află bufferul sursă și d} mulțimea paginilor în care se află bufferul destinație. ##* Folosirea funcției memcpy} generează page fault în următoarele situații: ###* Cel puțin o pagină din s} sau d} este nevalidă. (nu a fost alocată în RAM, este pe swap sau un acces nevalid din partea programatorului) ###* Cel puțin o pagină din d} este validă, dar nu sunt drepturi de scriere. (copy-on-write, mapare PROT_READ) ###* Cel puțin o pagină din s} este validă, dar nu sunt drepturi de citire. (mapare PROT_NONE) ##* Folosirea funcției memcpy} nu generează page fault dacă toate paginile din s} sunt valide, cu drept de citire și dacă toate paginile din d} sunt valide, cu drept de scriere. # Dați exemplu de situație/aplicație în care este mai avantajos să se folosească un număr x} de kernel-level threads într-un proces și o situație/aplicație în care este mai avantajos să se folosească un număr y} de kernel-level threads, cu x_y}. Ambele situații se vor raporta la același sistem dat. #* Răspuns: ##* Este mai avantajos să se folosească un număr x} (mai mic) de kernel-level threads într-un proces care execută operații CPU-intensive care folosesc puține apeluri blocante, deoarece utilizarea mai multor kernel-level threads ar însemna mai multe schimbări de context, care ar scădea performanța. ##* Este mai avantajos să se folosească un număr y} (mai mare) de kernel-level threads într-un proces care este I/O-intensive, având multe apeluri blocante, permițând unui număr mai mare de thread-uri să și continue execuția în cazul blocării unui thread. # Care este principala caracteristică a unui dispozitiv de tip caracter? Dați 2 exemple de astfel de dispozitive. #* Răspuns: Dispozitivele de tip caracter oferă acces secvențial și transfer de date la nivel de caracter, astfel au viteză redusă. ##* Exemple: tastatură, mouse, game controller, port serial, terminal, ==== 3CC, nr. 2 ==== # Pe un sistem pe 32 de biți, cu 512MB RAM și 512MB de swap, un proces execută secvența următoare de cod:<code c>int x = read_int_from_user(); void *a = malloc(x); memset(a, 0, x);</code>La un curs de Sisteme de Operare, profesorul întreabă “Care este valoarea minimă a lui x} pentru care apelul malloc} întoarce un pointer valid, dar apelul memset} duce la blocarea sistemului?”. Un student răspunde “1GB + 1B”. Profesorul răspunde “Cam pe acolo, dar valoarea reală este ceva mai mică”. De ce a spus profesorul acest lucru? #* Răspuns: Apelul malloc} folosește demand paging, alocând memorie pur virtuală, fără suport în memoria fizică. Apelul memset} necesită alocarea de pagini fizice, astfel că sistemul se va bloca în momentul în care nu mai are pagini fizice disponibile. Sistemul are disponibil 1 GB memorie fizică (512MB RAM și 512MB de swap) astfel că studentul a considerat că se va bloca la ocuparea întregii memorii fizice (1GB + 1B). În realitate, sistemul se va bloca la o valoare “ceva mai mică”, deoarece în memoria fizică se află pagini de memorie ale kernelului, cât și ale altor procese. # Prezentați un avantaj și un dezavantaj al folosirii user-level threads față de kernel-level threads. #* Răspuns: ##* Avantaje : ###* schimbarea de context nu implică kernelul, deci vom avea comutare rapidă ###* planificarea poate fi aleasă de aplicație; aplicația poate folosi acea planificare care favorizează creșterea performanțelor ###* firele de execuție pot rula pe orice sistem de operare, inclusiv pe sisteme de operare care nu suportă fire de execuție la nivel kernel. ##* Dezavantaje : ###* kernel-ul nu știe de fire de execuție, astfel că dacă un fir de execuție face un apel blocant toate firele de execuție planificate de aplicație vor fi blocate ###* nu se pot utiliza la maximum resursele hardware: kernelul va vedea un singur fir de execuție și va planifica procesul respectiv pe maximum un procesor, chiar dacă aplicația ar avea mai multe fire de execuție planificabile în același timp. # Care sunt cele două caracteristici importante ale unui dispozitiv de tip bloc? Dați 2 exemple de astfel de dispozitive. #* Răspuns: Dispozitivele de tip bloc oferă acces aleator și transfer de date la nivel de bloc, astfel au o viteză ridicată. ##* Exemple: discuri (hard-disk, floppy, unități optice, unități flash), sisteme de fișiere, memoria RAM. ==== Lucrare 4 ==== *15 mai, 09:05-09:15, EC004, seria CA *16 mai, 17:05-17:15, EC105, seria CC ==== 3CA, nr. 1 ==== # Care sunt dentry-urile existente în orice director pe un sistem de fișiere ext2/3 și ce reprezintă acestea? #* Răspuns: Orice director are intrările 2011-2012} și 2011-2012} care sunt dentry-uri către directorul curent, respectiv directorul părinte. # De ce nu este recomandată folosirea OpenVZ pentru kernel development? #* Răspuns: Deoarece OpenVZ este o soluție de virtualizare la nivel de kernel, însemnând că mașinile virtuale (containerele) partajează același kernel. În kernel development avem nevoie de o soluție de virtualizare în care putem găzdui un kernel separat astfel încât atunci când acesta este instabil să nu afecteze kernelul ce controlează mașina fizică. # Un dezvoltator rezolvă problema de signed/unsigned comparison din secvența de cod de mai jos:<code c>int i; unsigned int j; … if (i < j) …</code>astfel<code c>int i; unsigned int j; unsigned int k; … k = (unsigned int) i; if (k < j) …</code>De ce nu este aceasta o soluție corespunzătoare? #* Răspuns: Soluția propusă de către dezvoltator include un cast de la int} la unsigned_int}, care constă în adunarea valorii uint_max_1} la valoarea lui i}. Cel mai probabil k} va avea o valoare foarte mare, astfel că nu se va intra pe ramura if} a codului, dar k} nu va putea face overflow, deoarece va fi reprezentat pe același număr de biți ca și i}. Pentru mai multe informații, puteți consulta standardul C99, secțiunile 6.2.5 (9), 6.3.1.3, 6.3.1.8, ==== 3CA, nr. 2 ==== # Prezentați un avantaj și un dezavantaj al utilizării sistemelor de fișiere jurnalizate. #* Răspuns: # Avantaj: menținerea unui log al acțiunilor făcute asupra sistemului de fișiere, log ce poate fi consultat în cazul unei defecțiuni și poate ajuta la recuperarea datelor afectate în timpul defecțiunii. # Dezavantaj: este overhead-ul adus în procesare și spațiul pe suportul fizic consumat pentru menținerea jurnalului # Pe două sisteme identice sunt folosite soluții de virtualizare diferite: VMware Workstation, respectiv OpenVZ. Pe care din cele două sisteme gazdă vor exista mai multe procese în cazul pornirii unei mașini virtuale? #* Răspuns: În cazul VMware, sistemul de operare gazdă va vedea procesele sale plus un proces VMware sub care se ascund procesele mașinilor guest. În cazul OpenVZ, sistemul gazdă vede arborele cu procesele sale plus arborii fiecărui contianer OpenVZ. # Ce reprezintă conceptul de ”salt” în securitate și la ce este folosit? #* Răspuns: Conceptul de ”salt” se referă la o valoare (șir de biți, caractere) ce ajută la generarea mai eficientă a unui hash. Salt-ul ajută la mărirea entropiei hash-ului generat. ==== 3CC, nr. 1 ==== # Fie o implementare de inode care reține următoarele valori: permisiuni, număr de link-uri, uid, gid, dimensiune și zone directe. Fie fișierul ”a}” și un hard link către acesta, ”b}”. Prin ce diferă inode-urile celor două fișiere? #* Răspuns: Un hard link reprezintă un nou dentry care referă același inode, deci inode-urile celor două fișiere sunt identice. # Pe un sistem gazdă rulează 10 mașini virtuale care realizează numeroase copieri de fișiere între ele. Care soluție de virtualizare (Xen, OpenVZ, VMware Workstation) este mai eficientă în această situație și de ce? #* Răspuns: Deoarece OpenVZ este o soluție de virtualizare la nivel de kernel, containerele OpenVZ partajează același kernel și același sistem de fișiere astfel că, în OpenVZ, se pot copia ușor fișiere dintr-un container în altul. În cazul Xen sau VMware Workstation este necesară trecerea prin două spații kernel (al mașinilor virtuale sursă și destinație) și prin hipervizor. # De ce este considerată funcția memcpy} mai “sigură” decât funcția strcpy}? #* Răspuns: Deoarece funcția memcpy} specifică dimensiunea buffer-ului care trebuie copiat, în timp ce strcpy} presupune că buffer-ele sunt alocate cum trebuie, astfel încât strlen_sursa_sizeof_dest}. ==== 3CC, nr. 2 ==== # Pe un sistem se dorește conservarea numărului de inode-uri. Care din cele două tipuri de link-uri, hard sau sym, trebuie folosite în acest caz și de ce? #* Răspuns: Un hard link nu generează inode-uri noi, pe când un sym link este un inode nou, astfel că trebuie folosite hard link-uri. # Care dintre variantele VMware Workstation, respectiv OpenVZ oferă un grad mai mare de securitate și de ce? #* Răspuns: VMware Workstation oferă un grad mai mare de securitate, deoarece este o soluție de full virtualization, însemnând o izolare completă între mașini. În OpenVZ se partajează nucleul și coruperea sa într-o mașină duce la compromiterea întregului sistem. # Completați zona punctată a următoarei secvențe de cod cu un apel de bibliotecă, astfel încât: #* a) programul să fie vulnerabil la stack smashing; #* b) programul să nu fie vulnerabil la stack smashing. #* Motivați alegerile făcute.<code c>#define INPUT “1234” int main(void) { char a[2]; memcpy(a, INPUT, …); return 0; }</code> #* Răspuns: Pentru ca programul să fie vulnerabil la stack smashing, trebuie să permită copierea unui număr de octeți independent de dimensiunea buffer-ului destinație. Pentru ca programul să nu fie vulnerabil, trebuie să permită copierea unui număr de octeți mai mare decât dimensiunea buffer-ului destinație. # a) Apeluri de bibliotecă: strlen_input}, sizeof_input}, etc. #** b) Apeluri de bibliotecă: sizeof_a}, etc.