Differences

This shows you the differences between two versions of the page.

Link to this comparison view

so:laboratoare:laborator-06 [2018/04/03 18:45]
ioana_elena.ciornei [Exercițiul 3 - Detectare 'buffer underrun' folosind ElectricFence (1p)]
so:laboratoare:laborator-06 [2022/04/13 15:14] (current)
teodor_stefan.dutu [Exercițiul 3 - Detectare 'buffer underrun' folosind ElectricFence]
Line 2: Line 2:
  
  
-===== Materiale ajutătoare ===== 
- 
-  *[[http://​elf.cs.pub.ro/​so/​res/​laboratoare/​lab06-slides.pdf | lab06-slides.pdf]] 
-  *[[http://​elf.cs.pub.ro/​so/​res/​laboratoare/​lab06-refcard.pdf | lab06-refcard.pdf]] 
  
 ==== Nice to read ==== ==== Nice to read ====
Line 11: Line 7:
   * TLPI - Chapter 49, Memory mappings ​   * TLPI - Chapter 49, Memory mappings ​
   * TLPI - Chapter 50, Virtual memory operations   * TLPI - Chapter 50, Virtual memory operations
 +
 +===== Link-uri către secțiuni utile =====
 +
 +==== Linux ====
 +  * [[#​maparea_fisierelor|Maparea fișierelor]]
 +  * [[#​alocare_de_memorie_in_spatiul_de_adresa_al_procesului|Alocare de memorie în spațiul de adresă al procesului]]
 +  * [[#​maparea_dispozitivelor|Maparea dispozitivelor]]
 +  * [[#​demaparea_unei_zone_din_spatiul_de_adresa|Demaparea unei zone din spațiul de adresă]]
 +  * [[#​redimensionarea_unei_zone_mapate|Redimensionarea unei zone mapate]]
 +  * [[#​schimbarea_protectiei_unei_zone_mapate|Schimbarea protecției unei zone mapate]]
 +  * [[#​blocarea_paginarii|Blocarea paginării]]
 +  * [[#​electricfence|ElectricFence]]
 +
 +==== Windows ====
 +  * [[#​maparea_fisierelor1|Maparea fișierelor]]
 +  * [[#​alocare_de_memorie_in_spatiul_de_adresa_al_procesului1|Alocare de memorie în spațiul de adresă al procesului]]
 +  * [[#​demaparea_unei_zone_din_spatiul_de_adresa1|Demaparea unei zone din spațiul de adresă]]
 +  * [[#​schimbarea_protectiei_unei_zone_mapate1|Schimbarea protecției unei zone mapate]]
 +  * [[#​interogarea_zonelor_mapate|Interogarea zonelor mapate]]
 +  * [[#​blocarea_paginarii1|Blocarea paginării]]
  
 ===== Memoria virtuală ===== ===== Memoria virtuală =====
Line 51: Line 67:
 ===== Linux ===== ===== Linux =====
  
-Funcțiile cu ajutorul cărora se pot face cereri explicite asupra memoriei virtuale sunt funcțiile din familia ''​mmap(2)''​. Funcțiile folosesc ca unitate minimă de alocare //​pagina// ​(adică se poate aloca numai un număr întreg de pagini, iar adresele trebuie să fie aliniate corespunzător).+Funcțiile cu ajutorul cărora se pot face cereri explicite asupra memoriei virtuale sunt funcțiile din familia ''​mmap(2)''​. Funcțiile folosesc ca unitate minimă de alocare //pagina//.  
 +<note tip>​Se ​poate aloca numai un număr întreg de pagini, iar adresele trebuie să fie aliniate corespunzător.</​note>​
  
 ==== Maparea fișierelor ==== ==== Maparea fișierelor ====
Line 67: Line 84:
 </​code>​ </​code>​
  
-Funcția va întoarce în caz de eroare ''​MAP_FAILED''​. Dacă maparea s-a făcut cu succes, va întoarce un pointer spre o zonă de memorie din spațiul de adresă al procesului, zonă în care a fost mapat fișierul descris de descriptorul ''​fd'',​ începând cu offset-ul ''​offset''​. Folosirea parametrului ''​start''​ permite propunerea unei anumite zone de memorie la care să se facă maparea. Folosirea valorii ''​NULL''​ pentru parametrul ''​start''​ indică lipsa vreunei preferințe în ceea ce privește zona în care se va face alocarea. Adresa precizată prin parametrul ''​start''​ trebuie să fie multiplu de //​dimensiunea unei pagini//. Dacă sistemul de operare nu poate să mapeze fișierul la adresa cerută, atunci îl va mapa la o adresă apropiată și multiplu de dimensiunea unei pagini. ​Adresa la care se mapează fișierul ​este întoarsă de funcție+Funcția va întoarce în caz de eroare ''​MAP_FAILED''​. Dacă maparea s-a făcut cu succes, va întoarce un pointer spre o zonă de memorie din spațiul de adresă al procesului, zonă în care a fost mapat fișierul descris de descriptorul ''​fd'',​ începând cu offset-ul ''​offset''​. Folosirea parametrului ''​start''​ permite propunerea unei anumite zone de memorie la care să se facă maparea. Folosirea valorii ''​NULL''​ pentru parametrul ''​start''​ indică lipsa vreunei preferințe în ceea ce privește zona în care se va face alocarea. Adresa precizată prin parametrul ''​start''​ trebuie să fie multiplu de //​dimensiunea unei pagini//. Dacă sistemul de operare nu poate să mapeze fișierul la adresa cerută, atunci îl va mapa la o adresă apropiată și multiplu de dimensiunea unei pagini. ​Cea mai corespunzatoare adresa ​este si intoarsa
  
-Parametrul ''​prot''​ specifică tipul de acces care se dorește; poate fi ''​PROT_READ''​ (citire)''​PROT_WRITE''​ (scriere)''​PROT_EXEC''​ (execuție) ​sau ''​PROT_NONE''​; dacă zona e folosită altfel decât s-a declarat ​se va genera ​un semnal ''​SIGSEGV''​.+Parametrul ''​prot''​ specifică tipul de acces care se dorește:  
 +  *''​PROT_READ''​ (citire) 
 +  *''​PROT_WRITE''​ (scriere) ​ 
 +  *''​PROT_EXEC''​ (execuție) 
 +  *''​PROT_NONE''​.  
 +Cand zona e folosită altfel decât s-a declarat, este generat ​un semnal ''​SIGSEGV''​.
  
 Parametrul ''​flags''​ permite stabilirea tipului de mapare ce se dorește; poate lua următoarele valori (combinate prin SAU pe biți; trebuie să existe cel puțin ''​MAP_PRIVATE''​ sau ''​MAP_SHARED''​):​ Parametrul ''​flags''​ permite stabilirea tipului de mapare ce se dorește; poate lua următoarele valori (combinate prin SAU pe biți; trebuie să existe cel puțin ''​MAP_PRIVATE''​ sau ''​MAP_SHARED''​):​
-  *''​MAP_PRIVATE''​ - se folosește o politică de tip copy-on-write; zona va conține inițial o copie a fișierului,​ dar scrierile nu sunt făcute în fișier; modificările nu vor fi vizibile în alte procese dacă există mai multe procese care au făcut ''​mmap''​ pe aceeași zonă din același fișier +  *''​MAP_PRIVATE'' ​  ​Se folosește o politică de tip //copy-on-write//. Zona va conține inițial o copie a fișierului,​ dar scrierile nu sunt făcute în fișier. Modificările ​//nu vor fi vizibile în alte procese//, dacă există mai multe procese care au făcut ''​mmap''​ pe aceeași zonă din același fișier. 
-  *''​MAP_SHARED''​ - scrierile ​sunt actualizate imediat în toate mapările existente ​(în acest fel toate procesele care au realizat mapări vor vedea modificările); modificările vor fi vizibile și pentru un proces ce utilizează read/write deoarece ​mapările MAP_SHARED se fac peste paginile fizice din page cache iar apelurile ​read/write folosesc paginile fizice din page cache pentru a reduce numărul de citiri/​scrieri de pe disc; în schimb, actualizările pe disc vor avea loc la un moment de timp ulterior, nespecificat +  *''​MAP_SHARED'' ​   Scrierile ​sunt actualizate imediat în toate mapările existente. In acest fel toate procesele care au realizat mapări vor vedea modificările. Lucru datorat faptului că mapările ​''​MAP_SHARED'' ​se fac peste paginile fizice din page cacheiar apelurile ​r/folosesc paginile fizice din page cache pentru a reduce numărul de citiri/​scrieri de pe disc. Actualizările pe disc vor avea loc la un moment de timp ulterior, nespecificat. 
-  *''​MAP_FIXED''​ - dacă nu se poate face alocarea la adresa specificată de ''​start'',​ apelul va eșua +  *''​MAP_FIXED'' ​    ​Dacă nu se poate face alocarea la adresa specificată de ''​start'',​ apelul va eșua. 
-  *''​MAP_LOCKED''​ - se va bloca paginarea pe această zonă, în maniera [[http://​linux.die.net/​man/​2/​mlock|mlock]] +  *''​MAP_LOCKED'' ​   Se va bloca paginarea pe această zonă, în maniera [[http://​linux.die.net/​man/​2/​mlock|mlock]]. 
-  *''​MAP_ANONYMOUS''​ - se mapează memorie (argumentele ''​fd''​ și ''​offset''​ sunt ignorate)+  *''​MAP_ANONYMOUS''​ - Se mapează memorie ​RAM (argumentele ''​fd''​ și ''​offset''​ sunt ignorate).
  
- Este de remarcat că folosirea ''​MAP_SHARED''​ permite partajarea memoriei între procese care nu sunt înrudite. În acest caz, conținutul fișierului devine conținutul inițial al memoriei partajate și orice modificare făcută de procese în această zonă este copiată apoi în fișier, asigurând persistență prin sistemul de fișiere.  ​+ Este de remarcat ​faptul ​că folosirea ''​MAP_SHARED''​ permite partajarea memoriei între procese care nu sunt înrudite. În acest caz, conținutul fișierului devine conținutul inițial al memoriei partajate și orice modificare făcută de procese în această zonă este copiată apoi în fișier, asigurând persistență prin sistemul de fișiere.  ​
  
 === msync === === msync ===
Line 89: Line 111:
  
 unde ''​flags''​ poate fi: unde ''​flags''​ poate fi:
-  *''​MS_SYNC''​ - datele ​vor fi scrise în fișier și după aceea funcția ​se va termina+  *''​MS_SYNC''​ - Datele ​vor fi scrise în fișier și se așteaptă până se termină
-  *''​MS_ASYNC''​ - este inițiată secvența de salvare, dar nu se așteaptă terminarea ei. +  *''​MS_ASYNC''​ - Este inițiată secvența de salvare, dar nu se așteaptă terminarea ei. 
-  *''​MS_INVALIDATE''​ - se invalidează mapările zonei din alte procese, ​pentru a forța recitirea paginii în toate celelalte procese la următorul acces.+  *''​MS_INVALIDATE''​ - Se invalidează mapările zonei din alte procese, ​astfel incât procesele își vor face update cu datele noi înscrise.
  
 Apelul msync este util pentru a face scrierea paginilor modificate din page cache pe disc, cu scopul de a evita pierderea modificărilor în cazul unei căderi a sistemului. Apelul msync este util pentru a face scrierea paginilor modificate din page cache pe disc, cu scopul de a evita pierderea modificărilor în cazul unei căderi a sistemului.
Line 502: Line 524:
  
 <code c> <code c>
-LONG WINAPI ​VectoredHandler(+LONG CALLBACK ​VectoredHandler(
    ​PEXCEPTION_POINTERS ExceptionInfo    ​PEXCEPTION_POINTERS ExceptionInfo
 ); );
Line 525: Line 547:
 </​code>​ </​code>​
  
-În cazul unor excepții cauzate de un acces invalid la memorie''​ExceptionCode''​ va fi setat la ''​EXCEPTION_ACCESS_VIOLATION''​ sau ''​EXCEPTION_DATATYPE_MISALIGNMENT''​, iar ''​ExceptionAddress''​ la adresa instrucțiunii care a cauzat excepția''​NumberParameters''​ va fi setat pe 2, iar prima intrare în ''​ExceptionInformation''​ va fi ''​0''​ dacă s-a efectuat o operație de citire sau ''​1''​ dacă s-a efectuat o operație de scriere. A doua intrare din ''​ExceptionInformation''​ va conține adresa virtuală la care s-a încercat accesarea fără drepturi, fapt care a dus la generarea excepției. Așadar, corespondentul câmpului ''​si_addr''​ din structura ''​siginfo_t''​ de pe Linux este ''​ExceptionInformation''​ pe Windows, NU ''​ExceptionAddress''​.+În cazul unor excepții cauzate de un acces invalid la memorie
 +    * ''​ExceptionCode''​ va fi setat la ''​EXCEPTION_ACCESS_VIOLATION''​ sau ''​EXCEPTION_DATATYPE_MISALIGNMENT''​ 
 +    * ''​ExceptionAddress''​ la adresa instrucțiunii care a cauzat excepția 
 +    * ''​NumberParameters''​ va fi setat pe 2 
 +    * Prima intrare în ''​ExceptionInformation''​ va fi ''​0''​ dacă s-a efectuat o operație de citire sau ''​1''​ dacă s-a efectuat o operație de scriere. 
 +    * A doua intrare din ''​ExceptionInformation''​ va conține adresa virtuală la care s-a încercat accesarea fără drepturi, fapt care a dus la generarea excepției.
  
-Funcția ​de tratare a excepției înregistrată cu [[http://​msdn.microsoft.com/​en-us/​library/​ms679274%28VS.85%29.aspx|AddVectoredExceptionHandler]] trebuie să întoarcă ​''​EXCEPTION_CONTINUE_EXECUTION'', ​dacă excepția a fost tratată și se dorește continuarea execuției, sau ''​EXCEPTION_CONTINUE_SEARCH'' ​pentru a continua parcurgerea listei de funcții de tratare a excepțiilor,​ în caz că au fost înregistrate mai multe astfel de funcții. +<color red>​Așadar,​ corespondentul câmpului ''​si_addr''​ din structura ''​siginfo_t'' ​de pe Linux este ''​ExceptionInformation'' ​pe WindowsNU ''​ExceptionAddress''​. ​</​color>​
-===== Exerciții =====+
  
-===== Exercițiul 0 Joc interactiv ​(2p=====+Funcția de tratare a excepției înregistrată cu [[http://​msdn.microsoft.com/​en-us/​library/​ms679274%28VS.85%29.aspx|AddVectoredExceptionHandler]] trebuie să întoarcă una din următoarele valori ​(macro-uri)
 +   * ''​EXCEPTION_CONTINUE_EXECUTION'',​ dacă excepția a fost tratată și se dorește continuarea execuției 
 +   * ''​EXCEPTION_CONTINUE_SEARCH''​ pentru a continua parcurgerea listei de funcții de tratare a excepțiilor,​ în caz că au fost înregistrate mai multe astfel de funcții.
  
-  * Detalii desfășurare [[http://​ocw.cs.pub.ro/​courses/​so/​meta/​notare#​joc_interactiv|joc]].+===== Sumar =====
  
  
-<note important>​În ​rezolvarea laboratorului, ​folosiți arhiva ​de sarcini [[http://elf.cs.pub.ro/so/res/laboratoare/lab06-tasks.zip | lab06-tasks.zip]]+^ Operație ^ Linux ^ Windows^ 
-Platforma este la alegerea voastră. Punctajul maxim se poate obține fie pe Linuxfie pe Windows. Lucrați în mașina virtuală+| Maparea unui fișier ​ | [[#​maparea_fisierelor|mmap]] | [[#​maparea_fisierelor1|CreateFileMapping]] + [[#​maparea_fisierelor1|MapViewOfFile]] | 
 +| Demaparea unui fișier ​ | [[#​demaparea_unei_zone_din_spatiul_de_adresa|munmap]] | [[#​demaparea_unei_zone_din_spatiul_de_adresa1|UnmapViewOfFile]] | 
 +| Maparea unei zone de memorie ​ | [[#​maparea_fisierelor|mmap]] | [[#​alocare_de_memorie_in_spatiul_de_adresa_al_procesului1|VirtualAlloc]] | 
 +| Demaparea unei zone de memorie ​ | [[#​demaparea_unei_zone_din_spatiul_de_adresa|munmap]]| [[#​demaparea_unei_zone_din_spatiul_de_adresa1|VirtualFree]] | 
 +| Redimensionarea unei zone mapate ​ | [[#​redimensionarea_unei_zone_mapate|mremap]] | - | 
 +| Schimbarea protecției unei zone mapate ​ | [[#​schimbarea_protectiei_unei_zone_mapate|mprotect]] | [[#​schimbarea_protectiei_unei_zone_mapate1|VirtualProtect]] | 
 +| Blocarea paginării ​ | [[#​blocarea_paginarii|mlock]] | [[#​blocarea_paginarii1|VirtualLock]] | 
 +| Deblocarea paginării ​ | [[#​blocarea_paginarii|munlock]] | [[#​blocarea_paginarii1|VirtualUnlock]] | 
 +| Interogarea zonelor mapate ​ | - | [[#​interogarea_zonelor_mapate|VirtualQuery]] | 
 +|Excepții (accesul incorect la memorie) ​ |Programul primește SIGSEGV sau SIGBUS. \\ \\ Dacă se folosește o funcție de tip ''​sa_sigaction''​ pentru interceptarea semnalelor, atunci structura [[#​exceptii|siginfo_t]] primită ca parametru conține informații referitoare la ce a cauzat excepția (semnalul, adresa, cauza excepției).|Pentru tratarea excepțiilor se pot folosi funcțiile [[#​exceptii1|AddVectoredExceptionHandler]] și [[#​exceptii1|RemoveVectoredExceptionHandler]] împreună cu o funcție de tratare a excepțiilor.| 
 + 
 + 
 + 
 + 
 + 
 + 
 + 
 + 
 + 
 +===== Exerciții ===== 
 + 
 +<note important>​ 
 +În cadrul laboratoarelor vom folosi ​repository-ul ​de git al materiei SO - https://github.com/​systems-cs-pub-ro/so. Va trebui sa clonați repository-ul pe masinile virtuale folosind comanda: ''​git clone https://github.com/systems-cs-pub-ro/​so''​Dacă doriți să descărcați repositoryul în altă locație, folosiți comanda ''​git clone https://​github.com/​systems-cs-pub-ro/​so ${target}''​
 + 
 +Pentru a actualiza repository-ul,​ folosiți comanda ''​git pull origin master''​ din interiorul directorului în care se află repository-ulRecomandarea este să îl actualizați cât mai frecventînainte să începeți lucrul, pentru a vă asigura că aveți versiunea cea mai recentă. În cazul în care gitul detectează conflicte la nivelul vreunui fişier, folosiți următoarele comenzi pentru a vă păstra modificările:​ 
 +<​code>​ 
 +git stash 
 +git pull origin master 
 +git stash pop 
 +</​code>​ 
 + 
 +Pentru mai multe informații despre folosirea utilitarului git, urmați ghidul de la https://​gitimmersion.com.
 </​note>​ </​note>​
  
 <​note>​ Pentru a vă ajuta la implementarea exercițiilor din laborator, în directorul ''​utils''​ din arhivă există un fișier ''​utils.h''​ cu funcții utile. </​note>​ <​note>​ Pentru a vă ajuta la implementarea exercițiilor din laborator, în directorul ''​utils''​ din arhivă există un fișier ''​utils.h''​ cu funcții utile. </​note>​
  
-===== Linux (9p) ===== +==== Exercițiul 0 - GSOC ==== 
-==== Exercițiul 1 - Investigarea mapărilor folosind pmap (0.5p) ​====+ 
 +Google Summer of Code este un program de vară în care studenții 
 +(indiferent de anul de studiusunt implicați în proiecte Open Source 
 +pentru a își dezvolta skill-urile de programare, fiind răsplătiți cu o 
 +bursă a cărei valoare [[https://​developers.google.com/​open-source/​gsoc/​help/​student-stipends|depinde de țară]] 
 +([[https://​developers.google.com/​open-source/​gsoc|pagină principală GSOC]]). 
 + 
 +UPB se află în top ca număr de studenți acceptați; în fiecare an fiind undeva la aprox. 30-40 de studenți acceptați. 
 +Vă încurajăm să aplicați! 
 + 
 + 
 +===== Linux ===== 
 +==== Exercițiul 1 - Investigarea mapărilor folosind pmap ====
  
 Intrați în directorul ''​1-intro''​ și compilați sursa ''​intro.c''​. Rulați programul ''​intro'':<​code>​ Intrați în directorul ''​1-intro''​ și compilați sursa ''​intro.c''​. Rulați programul ''​intro'':<​code>​
Line 559: Line 630:
 Puteți observa că pentru bibliotecile partajate (de exemplu, ''​libc''​) sunt mapate trei zone: zona de cod (read-execute),​ zona .rodata (read-only) și zona .data (read-write). Puteți observa că pentru bibliotecile partajate (de exemplu, ''​libc''​) sunt mapate trei zone: zona de cod (read-execute),​ zona .rodata (read-only) și zona .data (read-write).
 </​note>​ </​note>​
-==== Exercițiul 2 - Scrierea în fișier - write vs. mmap (1p) ====+==== Exercițiul 2 - Scrierea în fișier - write vs. mmap ====
  
 Intrați în directorul ''​2-compare''​ și inspectați sursele ''​write.c''​ și ''​mmap.c'',​ apoi compilați. Obțineți timpul de execuție al celor două programe folosind comanda ''​time'':​ <code bash> ​ Intrați în directorul ''​2-compare''​ și inspectați sursele ''​write.c''​ și ''​mmap.c'',​ apoi compilați. Obțineți timpul de execuție al celor două programe folosind comanda ''​time'':​ <code bash> ​
Line 586: Line 657:
 <note tip>​Modificările aduse unei zone de memorie mapată cu ''​MAP_PRIVATE''​ nu vor fi vizible nici altor procese și nici nu vor ajunge în fișierul mapat de pe disc.</​note>​ <note tip>​Modificările aduse unei zone de memorie mapată cu ''​MAP_PRIVATE''​ nu vor fi vizible nici altor procese și nici nu vor ajunge în fișierul mapat de pe disc.</​note>​
  
-==== Exercițiul 3 - Detectare '​buffer underrun'​ folosind ElectricFence ​(1p) ====+==== Exercițiul 3 - Detectare '​buffer underrun'​ folosind ElectricFence ====
  
 Intrați în directorul ''​3-efence''​ și urmăriți sursa ''​bug.c''​. Compilați și rulați executabilul ''​bug'':<​code bash> Intrați în directorul ''​3-efence''​ și urmăriți sursa ''​bug.c''​. Compilați și rulați executabilul ''​bug'':<​code bash>
Line 604: Line 675:
  
 <note important>​ <note important>​
 +Dacă întâmpinați probleme în instalarea pachetului ''​electric-fence'',​ descărcați-l de [[http://​ro.archive.ubuntu.com/​ubuntu/​pool/​main/​e/​electric-fence/​electric-fence_2.2.4_amd64.deb| aici pentru x86_64]] și de [[http://​ro.archive.ubuntu.com/​ubuntu/​pool/​main/​e/​electric-fence/​electric-fence_2.2.4_i386.deb | aici pentru i386]] și instalați-l folosind comanda dpkg. 
 +
 <code bash> <code bash>
 $ wget http://​ro.archive.ubuntu.com/​ubuntu/​pool/​main/​e/​electric-fence/​electric-fence_2.2.4_amd64.deb $ wget http://​ro.archive.ubuntu.com/​ubuntu/​pool/​main/​e/​electric-fence/​electric-fence_2.2.4_amd64.deb
-$ dpkg -i electric-fence_2.2.4_amd64.deb+sudo dpkg -i electric-fence_2.2.4_amd64.deb
 </​code>​ </​code>​
 </​note>​ </​note>​
-==== Exercițiul 4 - Copierea fișierelor folosind mmap (2p) ====+==== Exercițiul 4 - Copierea fișierelor folosind mmap ====
  
 Intrați în directorul ''​4-cp''​ și completați sursa ''​mycp.c''​ astfel încât să realizeze copierea unui fișier primit ca argument. Pentru aceasta, mapați ambele fișiere în memorie și realizați copierea folosind ''​memcpy''​. Urmăriți comentariile cu ''​TODO''​ din sursă și următoarele hint-uri: Intrați în directorul ''​4-cp''​ și completați sursa ''​mycp.c''​ astfel încât să realizeze copierea unui fișier primit ca argument. Pentru aceasta, mapați ambele fișiere în memorie și realizați copierea folosind ''​memcpy''​. Urmăriți comentariile cu ''​TODO''​ din sursă și următoarele hint-uri:
    * Înainte de mapare, aflați dimensiunea fișierului sursă folosind [[http://​linux.die.net/​man/​2/​fstat | fstat]].    * Înainte de mapare, aflați dimensiunea fișierului sursă folosind [[http://​linux.die.net/​man/​2/​fstat | fstat]].
-   * Trunchiați fișierul destinație la dimensiunea fișierului sursă ​folosing ​[[https://​linux.die.net/​man/​2/​ftruncate | ftruncate]].+   * Trunchiați fișierul destinație la dimensiunea fișierului sursă ​folosind ​[[https://​linux.die.net/​man/​2/​ftruncate | ftruncate]].
    * Folosiți ''​MAP_SHARED''​ pentru mapare pentru a fi transmise schimbările în fișier: rețineți faptul că apelul mmap folosește una dintre opțiunile ''​MAP_SHARED''​ sau ''​MAP_PRIVATE''​ (una singură)    * Folosiți ''​MAP_SHARED''​ pentru mapare pentru a fi transmise schimbările în fișier: rețineți faptul că apelul mmap folosește una dintre opțiunile ''​MAP_SHARED''​ sau ''​MAP_PRIVATE''​ (una singură)
    * Pentru fișierul de intrare protecția trebuie să fie ''​PROT_READ'':​ fișierul a fost deschis read-only.    * Pentru fișierul de intrare protecția trebuie să fie ''​PROT_READ'':​ fișierul a fost deschis read-only.
Line 619: Line 692:
    * Argumentele funcției [[http://​man7.org/​linux/​man-pages/​man3/​memcpy.3.html|memcpy]] sunt, în ordine: destinația,​ sursa, numărul de octeți care să fie copiați.    * Argumentele funcției [[http://​man7.org/​linux/​man-pages/​man3/​memcpy.3.html|memcpy]] sunt, în ordine: destinația,​ sursa, numărul de octeți care să fie copiați.
    * Revedeți secțiunea [[#​maparea_fișierelor|maparea fișierelor]].    * Revedeți secțiunea [[#​maparea_fișierelor|maparea fișierelor]].
 +   * Asigurați persistența datelor pe sistemul de fișiere printr-un apel explicit [[https://​ocw.cs.pub.ro/​courses/​so/​laboratoare/​laborator-06#​msync|msync]]
  
 Puteți testa în felul următor: <code bash> Puteți testa în felul următor: <code bash>
Line 628: Line 702:
  
 <note tip>​Utilitarul ''​cp''​ folosește ''​read/​write''​ pentru a copia fișiere, în special pentru a limita consumul de memorie în cazul copierii unor fișiere de dimensiuni mari. De asemenea, în cazul mapării fișierului în memorie cu ''​mmap'',​ scrierea efectivă a datelor pe disc se va face într-un timp mai îndelungat,​ lucru care de cele mai multe ori nu este dorit (urmăriți ​ [[http://​stackoverflow.com/​a/​27987994|acest link]]). </​note>​ <note tip>​Utilitarul ''​cp''​ folosește ''​read/​write''​ pentru a copia fișiere, în special pentru a limita consumul de memorie în cazul copierii unor fișiere de dimensiuni mari. De asemenea, în cazul mapării fișierului în memorie cu ''​mmap'',​ scrierea efectivă a datelor pe disc se va face într-un timp mai îndelungat,​ lucru care de cele mai multe ori nu este dorit (urmăriți ​ [[http://​stackoverflow.com/​a/​27987994|acest link]]). </​note>​
-==== Exercițiul 5 - Tipuri de acces pentru pagini ​(3p) ====+ 
 +==== Exercițiul 5 - Tipuri de acces pentru pagini ====
  
 Intrați în directorul ''​5-prot''​ și inspectați sursa ''​prot.c''​. Intrați în directorul ''​5-prot''​ și inspectați sursa ''​prot.c''​.
Line 637: Line 712:
  
 <note important>​ Trebuie să ștergeți prima linie ''​old_action.sa_sigaction(signum,​ info, context);''​ pentru a putea rezolva a doua parte a exercițiului.</​note>​ <note important>​ Trebuie să ștergeți prima linie ''​old_action.sa_sigaction(signum,​ info, context);''​ pentru a putea rezolva a doua parte a exercițiului.</​note>​
-==== Exercițiul 6 - Page fault-uri ​(0.5p) ​====+==== Exercițiul 6 - Page fault-uri ====
  
 Intrați în directorul ''​6-faults''​ și urmăriți conținutul fișierului ''​fork-faults.c''​. Intrați în directorul ''​6-faults''​ și urmăriți conținutul fișierului ''​fork-faults.c''​.
Line 660: Line 735:
 <​note>​Pachetul ''​sysstat''​ mai conține și utilitarul ''​sar''​ prin care puteți colecta și realiza rapoarte despre activitatea sistemului. Pentru a activa salvarea datelor, trebuie setat flag-ul ''​ENABLED''​ din ''/​etc/​default/​sysstat''​. ​ <​note>​Pachetul ''​sysstat''​ mai conține și utilitarul ''​sar''​ prin care puteți colecta și realiza rapoarte despre activitatea sistemului. Pentru a activa salvarea datelor, trebuie setat flag-ul ''​ENABLED''​ din ''/​etc/​default/​sysstat''​. ​
 Cu ajutorul utilitarului ''​sar''​ puteți monitoriza informații precum încărcarea CPU-ului, utilizarea memoriei și a paginilor, operațiile de I/O, activitatea proceselor. Detalii puteți afla din [[http://​www.cyberciti.biz/​tips/​identifying-linux-bottlenecks-sar-graphs-with-ksar.html| tutorial sar]]. </​note>​ Cu ajutorul utilitarului ''​sar''​ puteți monitoriza informații precum încărcarea CPU-ului, utilizarea memoriei și a paginilor, operațiile de I/O, activitatea proceselor. Detalii puteți afla din [[http://​www.cyberciti.biz/​tips/​identifying-linux-bottlenecks-sar-graphs-with-ksar.html| tutorial sar]]. </​note>​
-==== Exercițiul 7 - Blocarea paginării ​(1p) ====+==== Exercițiul 7 - Blocarea paginării ====
  
 Vă aflați într-o situație în care trebuie să procesați în timp real datele dintr-un buffer și vreți să evitați swaparea paginilor. Intrați în directorul ''​7-paging''​ și completați ''​TODO-urile''​ astfel încât paginarea va fi blocată pentru variabila //data// pe parcursul lucrului cu aceasta, iar la final va fi deblocată. Deși pe Linux adresa va fi aliniată automat la dimensiunea unei pagini, acest lucru nu se întâmplă pe toate sistemele POSIX compliant, prin urmare este o practică bună să o aliniem manual. Vă aflați într-o situație în care trebuie să procesați în timp real datele dintr-un buffer și vreți să evitați swaparea paginilor. Intrați în directorul ''​7-paging''​ și completați ''​TODO-urile''​ astfel încât paginarea va fi blocată pentru variabila //data// pe parcursul lucrului cu aceasta, iar la final va fi deblocată. Deși pe Linux adresa va fi aliniată automat la dimensiunea unei pagini, acest lucru nu se întâmplă pe toate sistemele POSIX compliant, prin urmare este o practică bună să o aliniem manual.
Line 671: Line 746:
  
 <note tip>​Limita maximă pentru care se poate executa cu succes ''​mlock''​ este dată de ''​RLIMIT_MEMLOCK''​ (max locked memory). Aceasta are de obicei valoarea ''​64KB''​ și poate fi configurată folosind ''​ulimit''​.</​note>​ <note tip>​Limita maximă pentru care se poate executa cu succes ''​mlock''​ este dată de ''​RLIMIT_MEMLOCK''​ (max locked memory). Aceasta are de obicei valoarea ''​64KB''​ și poate fi configurată folosind ''​ulimit''​.</​note>​
 +
 ==== Bonus Linux ==== ==== Bonus Linux ====
  
-=== 1 so karma - Schimbarea tipului de acces pentru pagini din segmentul de cod ===+=== Schimbarea tipului de acces pentru pagini din segmentul de cod ===
  
 Intrați în directorul ''​8-hack''​. Programul apelează funcția //foo()//. Având determinată pagina în care se află funcția în spațiul de adresă al procesului, i se schimbă drepturile de acces în ''​PROT_READ|PROT_WRITE|PROT_EXEC''​ și se modifică valoarea de retur a funcției (se scrie în segmentul de cod). Intrați în directorul ''​8-hack''​. Programul apelează funcția //foo()//. Având determinată pagina în care se află funcția în spațiul de adresă al procesului, i se schimbă drepturile de acces în ''​PROT_READ|PROT_WRITE|PROT_EXEC''​ și se modifică valoarea de retur a funcției (se scrie în segmentul de cod).
Line 681: Line 757:
 Modificați drepturile de acces în ''​PROT_READ|PROT_EXEC'',​ compilați și rulați din nou. Observați că fără drepturi de scriere execuția programului este încheiată de un semnal SIGSEGV. ​ Modificați drepturile de acces în ''​PROT_READ|PROT_EXEC'',​ compilați și rulați din nou. Observați că fără drepturi de scriere execuția programului este încheiată de un semnal SIGSEGV. ​
  
-===== Windows ​(9p) =====+===== Windows =====
  
-==== Exercițiul 1 - Maparea memoriei ​(0.5p) ​====+==== Exercițiul 1 - Maparea memoriei ====
  
 Deschideți proiectul ''​1-intro''​. Inspectați și compilați sursa ''​intro.c''​. Rulați proiectul, iar în paralel urmăriți comportamentul programului ''​intro''​ în Task Manager - în special coloanele ''​Memory - Working Set'',​ ''​Memory - Private Working Set''​ și ''​Page Faults''​. Pentru a vedea o listă completă cu coloanele care pot fi activate accesați Task Manager(tabul Processes)->​View->​Select Columns. Deschideți proiectul ''​1-intro''​. Inspectați și compilați sursa ''​intro.c''​. Rulați proiectul, iar în paralel urmăriți comportamentul programului ''​intro''​ în Task Manager - în special coloanele ''​Memory - Working Set'',​ ''​Memory - Private Working Set''​ și ''​Page Faults''​. Pentru a vedea o listă completă cu coloanele care pot fi activate accesați Task Manager(tabul Processes)->​View->​Select Columns.
  
-==== Exercițiul 2 - Crearea unor rutine în mod dinamic ​(1p) ====+==== Exercițiul 2 - Crearea unor rutine în mod dinamic ====
  
 Deschideți proiectul ''​2-dyn''​ și urmăriți sursa ''​dyn.c''​. Programul alocă memorie în spațiul de adresă al procesului pentru a stoca o rutină, de forma ''​dyncode''​. Rutina va incrementa parametrul primit și va întoarce această valoare. Urmăriți conțintul lui ''​code''​. Deși în acest caz conținutul rutinei este definit direct în program prin ''​code'',​ el ar putea fi primit în orice alt mod (fișier, rețea). Deschideți proiectul ''​2-dyn''​ și urmăriți sursa ''​dyn.c''​. Programul alocă memorie în spațiul de adresă al procesului pentru a stoca o rutină, de forma ''​dyncode''​. Rutina va incrementa parametrul primit și va întoarce această valoare. Urmăriți conțintul lui ''​code''​. Deși în acest caz conținutul rutinei este definit direct în program prin ''​code'',​ el ar putea fi primit în orice alt mod (fișier, rețea).
  
-==== Exercițiul 3 - Mapare fișiere în memorie ​(1.5p) ​====+==== Exercițiul 3 - Mapare fișiere în memorie ====
  
 Să se scrie un program care copiază un fișier folosind proiectul ''​3-copy''​. Programul primește ca argumente numele fișierului sursă și numele fișierului desținație,​ mapează în memorie cele două fișiere și copiază conținutul primului fișier folosind ''​memcpy(3)''​. Pentru aflarea lungimii fișierului sursă s-a folosit [[http://​msdn.microsoft.com/​en-us/​library/​aa364946(VS.85).aspx| GetFileAttributesEx]]. Fișierul destinație trebuie trunchiat la dimensiunea fișierului sursă folosind [[http://​msdn.microsoft.com/​en-us/​library/​aa365541(VS.85).aspx| SetFilePointer]] și [[http://​msdn.microsoft.com/​en-us/​library/​aa365531(VS.85).aspx| SetEndOfFile]]. Să se scrie un program care copiază un fișier folosind proiectul ''​3-copy''​. Programul primește ca argumente numele fișierului sursă și numele fișierului desținație,​ mapează în memorie cele două fișiere și copiază conținutul primului fișier folosind ''​memcpy(3)''​. Pentru aflarea lungimii fișierului sursă s-a folosit [[http://​msdn.microsoft.com/​en-us/​library/​aa364946(VS.85).aspx| GetFileAttributesEx]]. Fișierul destinație trebuie trunchiat la dimensiunea fișierului sursă folosind [[http://​msdn.microsoft.com/​en-us/​library/​aa365541(VS.85).aspx| SetFilePointer]] și [[http://​msdn.microsoft.com/​en-us/​library/​aa365531(VS.85).aspx| SetEndOfFile]].
  
-==== Exercițiul 4 - Tipuri de acces pentru pagini ​(3p) ====+==== Exercițiul 4 - Tipuri de acces pentru pagini ====
  
 Încărcați proiectul ''​4-prot''​ și inspectați sursa ''​libvm.c''​. Încărcați proiectul ''​4-prot''​ și inspectați sursa ''​libvm.c''​.
  
-Să se creeze ​o zonă de memorie în spațiul de adresă, formată din trei pagini virtuale (folosiți un singur apel ''​VirtualAlloc''​). ​Prima pagina nu va avea vreun drept, a două va avea drepturi de citire, iar a treia va avea drepturi de scriere (folosiți ​''​VirtualProtect''​ pentru a configura ​drepturile fiecărei pagini)Să se testeze comportamentul programului când se fac accese ​de citire ​și scriere în aceste zoneUrmăriți comentariile cu ''​TODO 1''​.+Creați ​o zonă de memorie în spațiul de adresă ​al procesului, formată din trei pagini virtuale (folosiți un singur apel ''​VirtualAlloc''​). ​Folosind ​''​VirtualProtect''​ pentru a configuara ​drepturile fiecărei pagini, realizați modificările necesare astfel încât: 
 +   * prima pagină nu are niciun drept. 
 +   * a doua pagină are doar drepturi ​de citire. 
 +   * a treia pagină are drepturi de scriere.
  
-Adăugați un handler de tratare a excepțiilor care să remapeze incremental zonele cu protecție ​de citire și scriere ​la generarea excepțiilor. Astfel, dacă pagina nu are vreun drept, la page fault se va remapa cu drepturi de citire. Dacă pagina are drepturi de citire, la page fault se va remapa cu drepturi de citire + drepturi de scriere. Urmăriți comentariile cu ''​TODO ​2''​.+Testați comportamentul programului când se fac accese ​de citire și scriere ​în aceste zone. Urmăriți comentariile cu ''​TODO ​1''​.
  
-==== Exercițiul 5 - Detectare '​buffer overrun'​ - implementare utilitar asemănător cu Electric Fence (2p) ====+Adăugați un handler de tratare a excepțiilor care să remapeze incremental zonele cu protecție de citire și scriere la generarea excepțiilor. Astfel, dacă pagina nu are niciun drept, la page fault se va remapa cu drepturi de citire. Dacă pagina are drepturi de citire, la page fault se va remapa cu drepturi de citire + drepturi de scriere. Urmăriți comentariile cu ''​TODO 2''​. 
 + 
 +<note important>​ 
 +Revedeți secțiunea [[#​exceptii1|Excepții]]. 
 +</​note>​ 
 + 
 + 
 + 
 +==== Exercițiul 5 - Detectare '​buffer overrun'​ - implementare utilitar asemănător cu Electric Fence ====
  
 Încărcați proiectul ''​5-ef''​ și inspectați sursa, ignorând pentru moment funcția ''​MyMalloc''​. Compilați și rulați proiectul. Încărcați proiectul ''​5-ef''​ și inspectați sursa, ignorând pentru moment funcția ''​MyMalloc''​. Compilați și rulați proiectul.
Line 711: Line 798:
 Testați din nou folosind de data aceasta ''​MyMalloc'',​ atât în cazul în care inițializarea vectorului depășește dimensiunea alocată, cât și în cazul în care nu depășește. Testați din nou folosind de data aceasta ''​MyMalloc'',​ atât în cazul în care inițializarea vectorului depășește dimensiunea alocată, cât și în cazul în care nu depășește.
  
-==== Exercițiul 6 - Blocarea paginării ​(1p) ====+==== Exercițiul 6 - Blocarea paginării ====
  
 Vă aflați într-o situație în care trebuie să procesați în timp real datele dintr-un buffer și vreți să evitați swaparea paginilor. Intrați în directorul ''​6-lock''​ și completați ''​TODO-urile''​ astfel încât paginarea să fie blocată pentru variabila //data// pe parcursul lucrului cu aceasta, iar la final să fie deblocată. Adresa trebuie aliniată la limita unei pagini. Vă aflați într-o situație în care trebuie să procesați în timp real datele dintr-un buffer și vreți să evitați swaparea paginilor. Intrați în directorul ''​6-lock''​ și completați ''​TODO-urile''​ astfel încât paginarea să fie blocată pentru variabila //data// pe parcursul lucrului cu aceasta, iar la final să fie deblocată. Adresa trebuie aliniată la limita unei pagini.
Line 721: Line 808:
   * Care sunt cele mai importante diferențe între metoda [[https://​docs.python.org/​2/​library/​mmap.html|mmap]] din modulul de Python cu același nume și funcția [[http://​man7.org/​linux/​man-pages/​man2/​mmap.2.html|nativă]] din Linux?   * Care sunt cele mai importante diferențe între metoda [[https://​docs.python.org/​2/​library/​mmap.html|mmap]] din modulul de Python cu același nume și funcția [[http://​man7.org/​linux/​man-pages/​man2/​mmap.2.html|nativă]] din Linux?
        
-===== Soluții ===== 
- 
- ​[[http://​elf.cs.pub.ro/​so/​res/​laboratoare/​lab06-sol.zip | Soluții exerciții laborator 6]] 
  
 ===== Resurse Utile ===== ===== Resurse Utile =====
so/laboratoare/laborator-06.1522770315.txt.gz · Last modified: 2018/04/03 18:45 by ioana_elena.ciornei
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0