Differences

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

Link to this comparison view

so:cursuri:curs-06 [2014/03/22 21:43]
razvan.deaconescu [Investigarea mapării folosind pmap]
so:cursuri:curs-06 [2019/03/24 14:10] (current)
razvan.deaconescu
Line 1: Line 1:
 ====== Curs 06 - Memoria virtuală ====== ====== Curs 06 - Memoria virtuală ======
- 
-<​html>​ 
-<iframe src="​http://​prezi.com/​embed/​qshrq7oeytj2/?​bgcolor=ffffff&​amp;​lock_to_path=0&​amp;​autoplay=0&​amp;​autohide_ctrls=0&​amp;​features=undefined&​amp;​disabled_features=undefined"​ width="​550"​ height="​400"​ frameBorder="​0"></​iframe>​ 
-</​html>​ 
  
   * [[http://​prezi.com/​qshrq7oeytj2/?​utm_campaign=share&​utm_medium=copy&​rc=ex0share | Curs 06 - Memoria virtuală (vizualizare Prezi)]]   * [[http://​prezi.com/​qshrq7oeytj2/?​utm_campaign=share&​utm_medium=copy&​rc=ex0share | Curs 06 - Memoria virtuală (vizualizare Prezi)]]
   * [[http://​elf.cs.pub.ro/​so/​res/​cursuri/​SO_Curs-06.pdf | Curs 06 - Memoria virtuală (PDF)]]   * [[http://​elf.cs.pub.ro/​so/​res/​cursuri/​SO_Curs-06.pdf | Curs 06 - Memoria virtuală (PDF)]]
 +
 +  * [[https://​drive.google.com/​open?​id=1jsFIY2bG2QssLX1X9AWn4_0Ec2x_hK9oOGohmFqKSRM|Notițe de curs]]
  
   * Suport curs   * Suport curs
     * Operating Systems Concepts Essentials     * Operating Systems Concepts Essentials
       * Capitolul 8 - Virtual Memory       * Capitolul 8 - Virtual Memory
-    * Modern Operating Systems+    * Modern Operating Systems, 2nd Ed.
       * Capitolul 4 - Memory Management       * Capitolul 4 - Memory Management
         * Secțiunile 4.4, 4.5         * Secțiunile 4.4, 4.5
 +    * Modern Operating Systems, 3rd Ed.
 +      * Capitolul 3 - Memory Management
 +        * Secțiunile 3.4, 3.5
 +    * [[http://​duartes.org/​gustavo/​blog/​post/​anatomy-of-a-program-in-memory/​|Anatomy of a Program in Memory]]
 +
 +<​html>​
 +  <​center>​
 +    <iframe src="​https://​prezi.com/​embed/​qshrq7oeytj2/?​bgcolor=ffffff&​amp;​lock_to_path=0&​amp;​autoplay=0&​amp;​autohide_ctrls=0&​amp;​features=undefined&​amp;​disabled_features=undefined"​ width="​550"​ height="​400"​ frameBorder="​0"></​iframe>​
 +  </​center>​
 +</​html>​
  
 ===== Demo-uri ===== ===== Demo-uri =====
Line 56: Line 64:
 ==== Investigarea mapării folosind pmap ==== ==== Investigarea mapării folosind pmap ====
  
-Vrem să vizualizăm spațiul virtual de adrese al unui proces. Pentru aceasta, accesăm subdirectorul ''​pmap'';​ urmărim conținutul fișierului ''​pmap.c'';​ facem mapări (folosind apelul ''​mmap''​) folosind diverse flag-uri.+Vrem să vizualizăm spațiul virtual de adrese al unui proces. Pentru aceasta, accesăm subdirectorul ''​pmap/'';​ urmărim conținutul fișierului ''​pmap.c'';​ facem mapări (folosind apelul ''​mmap''​) folosind diverse flag-uri.
  
 Compilăm programul folosind ''​make''​ și apoi îl rulăm:<​code bash> Compilăm programul folosind ''​make''​ și apoi îl rulăm:<​code bash>
Line 76: Line 84:
 ==== Alocarea de memorie virtuală ==== ==== Alocarea de memorie virtuală ====
  
-Vrem să urmărim modul în care se alocă memorie virtuală în spațiul virtual de adrese al unui proces. Pentru aceasta, accesăm subdirectorul ''​allocation'';​ urmărim conținutul fișierului ''​allocation.c'';​ în cadrul fișierului se fac alocări de memorie virtuală folosind pe rând apelul ''​malloc''​ și apelul ''​mmap''​.+Vrem să urmărim modul în care se alocă memorie virtuală în spațiul virtual de adrese al unui proces. Pentru aceasta, accesăm subdirectorul ''​allocation/'';​ urmărim conținutul fișierului ''​allocation.c'';​ în cadrul fișierului se fac alocări de memorie virtuală folosind pe rând apelul ''​malloc''​ și apelul ''​mmap''​.
  
 Compilăm fișierul folosind comanda ''​make''​. Compilăm fișierul folosind comanda ''​make''​.
Line 98: Line 106:
 Observăm de asemenea, că se realizează un număr redus de apeluri de sistem ''​brk''​ raportat la cele ''​1024''​ de apeluri de bibliotecă ''​malloc''​. Un apel ''​brk''​ alocă un pool mai mare de memorie care va fi apoi folosit la apeluri viitoare ''​malloc'';​ realizează o prealocare. Observăm de asemenea, că se realizează un număr redus de apeluri de sistem ''​brk''​ raportat la cele ''​1024''​ de apeluri de bibliotecă ''​malloc''​. Un apel ''​brk''​ alocă un pool mai mare de memorie care va fi apoi folosit la apeluri viitoare ''​malloc'';​ realizează o prealocare.
  
-Pentru a vedea comportamentului funcției de bibliotecă ''​mallooc'',​ actualizăm codul astfel încât ''​malloc''​ să aloce, la fel ca ''​mmap''​ calupuri de ''​1MB''​ de memorie. Adică bucla ''​for''​ aferentă să arate așa:<​code c>+Pentru a vedea comportamentului funcției de bibliotecă ''​malloc'',​ actualizăm codul astfel încât ''​malloc''​ să aloce, la fel ca ''​mmap''​ calupuri de ''​1MB''​ de memorie. Adică bucla ''​for''​ aferentă să arate așa:<​code c>
  for (cnt = 0; cnt < NUM_ROUNDS; cnt++) {  for (cnt = 0; cnt < NUM_ROUNDS; cnt++) {
  puts("​Using malloc to allocate 1024 sets of 1024 bytes."​);​  puts("​Using malloc to allocate 1024 sets of 1024 bytes."​);​
Line 113: Line 121:
 </​code>​ </​code>​
  
-Observăm că acum și funcția de bibliotecă ''​malloc''​ folosește în spate tot apelul de sistem ''​mmap''​. Acesta alocă doar memorie virtuală de unde și comportamentul. De la un valoare dată, alocarea cu ''​malloc''​ folosește apelul de sistem ''​mmap''​.+Observăm că acum și funcția de bibliotecă ''​malloc''​ folosește în spate tot apelul de sistem ''​mmap''​. Acesta alocă doar memorie virtuală de unde și comportamentul. De la valoare dată, alocarea cu ''​malloc''​ folosește apelul de sistem ''​mmap''​.
  
 <spoiler Despre apelul malloc> <spoiler Despre apelul malloc>
Line 129: Line 137:
 ==== Paginare la cerere (demand paging) ==== ==== Paginare la cerere (demand paging) ====
  
-Vrem să vizualizăm spațiul virtual ​de adrese al unui proces. Pentru aceasta, accesăm subdirectorul ''​pmap'';​ urmărim conținutul fișierului ''​pmap.c''; ​facem mapări (folosind ​apelul ​''​mmap''​) folosind diverse flag-uri.+Vrem să urmărim modul în care se alocă pagini ​de memorie fizică la cerere, ​proces ​care se numește ''​(on) demand paging''​. Pentru aceasta, accesăm subdirectorul ''​demand-paging/​'';​ urmărim conținutul fișierului ''​demand-paging.c''; ​în cadrul fișierului alocăm memorie virtuală folosind ''​mmap'' ​și apoi accesăm primul octet al fiecărei pagini alocate.
  
-    * Intrați în directorul ''​4-demand-paging/''​. +Compilăm codul sursă ​folosind comanda ''​make''​. 
-    * Consultați fișierul ''​demand-paging.c''​. + 
-    * Compilați sursele ​folosind comanda ''​make''​. +Avem nevoie de două console: 
-    * Deschideți o consolă nouă. +  * Într-o consolă ​rulăm ​executabilul aferent:<​code>​
-    * Într-o consolă ​rulați ​executabilul aferent:<​code>​+
 ./​demand-paging ./​demand-paging
 </​code>​ </​code>​
-    ​* Într-o altă consolă ​vizualizați ​dimensiunea spațiului fizic ocupat și a a spatiului virtual ocupat, folosind comanda:<​code bash>+  ​* Într-o altă consolă ​vizualizăm ​dimensiunea spațiului fizic ocupat și a a spatiului virtual ocupat, folosind comanda:<​code bash>
 watch -n 1 ps -o pid,​rss,​vsz,​cmd -p $(pidof demand-paging) watch -n 1 ps -o pid,​rss,​vsz,​cmd -p $(pidof demand-paging)
 </​code>​ </​code>​
-    * Observați ​cum crește dimensiunea spațiului spatiului virtual fără a crește dimensiunea spațiului fizic în prima parte. + 
-      * Observați cum crește dimensiunea spațiului fizic în a doua parte (fără a crește dimensiunea spațiului virtual). +Observăm ​cum crește dimensiunea spațiului spatiului virtual ​(coloana ''​VSZ''​) ​fără a crește dimensiunea spațiului fizic în prima parte. ​Se face alocare de memorie virtuală, fără paginare - adică fără alocare de spațiu fizic aferent. În partea a doua, observați cum crește dimensiunea spațiului fizic (coloana ''​RSS''​) ​în a doua parte (fără a crește dimensiunea spațiului virtual). ​Aceasta este //(on) demand paging//, cu alocarea paginilor fizice necesare la nevoie. 
-    * Într-o consolă ​rulați ​executabilul aferent:<​code>​+ 
 +Ca să detaliem, urmărim page fault-urile realizate pe parcursul rulării programului. Folosim, la fel, două console: 
 +  * Într-o consolă ​rulăm ​executabilul aferent:<​code>​
 ./​demand-paging ./​demand-paging
 </​code>​ </​code>​
-    ​* Într-o altă consolă ​vizualizați ​numărul de page fault-uri generate de program (''​min_flt''​ este coloana de interes, ''​maj_flt''​ este pentru interacțiuni cu discul -- swapping):<​code bash>+  ​* Într-o altă consolă ​vizualizăm ​numărul de page fault-uri generate de program (''​min_flt''​ este coloana de interes, ''​maj_flt''​ este pentru interacțiuni cu discul -- swapping):<​code bash>
 watch -n 1 ps -o pid,​min_flt,​maj_flt,​cmd -p $(pidof demand-paging) watch -n 1 ps -o pid,​min_flt,​maj_flt,​cmd -p $(pidof demand-paging)
 </​code>​ </​code>​
-    * Observați cum nu există page fault-uri în prima pare a rulării programului. +Observați cum nu există page fault-uri în prima pare a rulării programului, în momentul în care facem mapări de memorieDar apar page fault-uri în a doua parte a rulării programului.
-      * Observați cum există ​page fault-uri în a doua parte a rulării programului. +
-      * Câte page fault-uri sunt generate la o "​trecere prin chunk"?​ De ce?+
  
-==== Page-Faulturi ====+Câte page fault-uri sunt generate la o "​trecere prin chunk"?​ De ce?
  
-Vrem să vizualizăm spațiul virtual de adrese al unui procesPentru aceasta, accesăm subdirectorul ''​pmap'';​ urmărim conținutul fișierului ''​pmap.c'';​ facem mapări (folosind apelul ''​mmap''​folosind diverse flag-uri.+<spoiler Răspuns> 
 +Se generează 256 page fault-uriAsta se întâmplă pentru ca la fiecare "​trecere prin chunk" se accesează 256 pagini, fiecare pagină având câte 4KB, pentru un total de 1MBUn page fault înseamnă alocarea ​(on demanda unei pagini fizice. 
 +</​spoiler>​
  
-    * Intrați ​în directorul ​''​5-fork-faults/''​+==== Page fault-uri la fork (copy-on-write) ==== 
-    * Consultațfișierului ''​fork-faults.c''​. + 
-    * **Câte page-fault-uri** credeți că se realizează la rulare? +Vrem să urmărim realizarea page fault-urilor ​în urma unui apel ''​fork'';​ page fault-urilor vor fi cauzate de mecanismul de copy-on-write în momentul în care unul dintre cele două procese (copil sau părinte) scrie în zona respectivă. Pentru aceasta, accesăm subdirectorul ''​fork-faults''​; urmărim conținutul ​fișierului ''​fork-faults.c''​. ​În cadrul fișierului ''​fork-faults.c''​ se execută următorii pași: 
-    * Compilați ​fișierul+  - se alocă memorie virtuală folosind ''​mmap''​ 
-    * Rulați programul ​''​fork-faults''​. +  - se alocă memorie fizică pentru paginile de mai sus, folosind //(on) demand paging// prin accesarea primului octet al fiecărei pagini 
-    * Folosiț''​ENTER''​ pentru a continua programul, dar după rularea ''​pidstat''​ (vedeți ​mai jos). +  - se creează un proces nou 
-    * Pe un alt terminal sau tab de terminal folosiți ​utilitarul ''​pidstat''​ din pachetul ''​sysstat''​ care permite monitorizarea page fault-urilor unui proces (prin intermediul argumentului ''​-r''​). +  - procesul copil citește valoarea din prima jumătate a numărului de pagini (**doar** citește) 
-      * Dacă nu merge comanda ''​pidstat''​ trebuie să instalați ​pachetul ''​sysstat''​ folosind comanda:<​code bash>+  ​procesul copil scrie o valoare în cadrul fiecărei pagini din a două jumătate 
 +  ​procesul părinte scrie o valoare în toate paginile 
 + 
 +Ca să urmărim ce se întâmplă, compilăm ​fișierul ​folosind ​''​make''​. ​Apoi rulăm programul obținut:<​code bash> 
 +./​fork-faults 
 +</​code>​ Folosim ​''​ENTER''​ pentru a continua programul, dar după rularea ''​pidstat''​ (mai jos). 
 + 
 +Într-o ​altă consolă folosim ​utilitarul ''​pidstat''​ din pachetul ''​sysstat''​ care permite monitorizarea page fault-urilor unui proces (prin intermediul argumentului ''​-r''​). Dacă nu există ​comanda ''​pidstat''​ trebuie să instalăm ​pachetul ''​sysstat''​ folosind comanda:<​code bash>
 apt-get install sysstat apt-get install sysstat
 </​code>​ </​code>​
-    * Folosiți comanda <code bash>+ 
 +Pentru a rula ''​pidstat''​ șa urmări page fault-urile,​ folosim, pe a doua consolă, ​comanda<​code bash>
 pidstat -r -T ALL -p $(pidof fork-faults) 5 100 pidstat -r -T ALL -p $(pidof fork-faults) 5 100
-</​code> ​pentru a urmări page fault-urile. +</​code>​ Comanda de mai sus afișează câte un mesaj la fiecare 5 secunde. ​În prima consolă ​apăsăm ''​ENTER'' ​pentru a continua rularea și urmărim informațiile ​afișate de ''​pidstat''​, apoi continuăm apăsarea ''​ENTER''​ etc
-      * Comanda de mai sus vă afișează câte un mesaj la fiecare 5 secunde. ​Sincronizați ​apăsarea tastei ​''​ENTER'' ​cu afișajul comenzii ​''​pidstat''​. + 
-    ​* ​Urmăriți evoluția numărului de page fault-uri pentru cele două procese: părinte și copil. +Urmărim, în outputul comenzii ''​pidstat'', ​evoluția numărului de page fault-uri pentru cele două procese: părinte și copil. Page fault-urile care apar în cazul unui copy-on-write în procesul copil vor fi vizibile ulterior și în procesul părinte. Observăm că procesul copil generează page fault-uri doar pe jumătate din pagini (cele în care scrie), iar procesul părinte generează page fault-uri pe toate paginile. Asta pentru că un proces creează o copie a paginilor inițiale, dar lasă acele pagini ''​read-only'',​ iar alt proces primește page fault dar doar schimbă permisiunile din read-only în read-write.
-      * Page fault-urile care apar în cazul unui copy-on-write în procesul copil vor fi vizibile ulterior și în procesul părinte.+
so/cursuri/curs-06.1395517384.txt.gz · Last modified: 2014/03/22 21:43 by razvan.deaconescu
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