Pentru parcurgerea demo-urilor, folosim arhiva aferentă. Demo-urile rulează pe Linux. Descărcăm arhiva folosind comanda
wget http://elf.cs.pub.ro/so/res/cursuri/curs-05-demo.zip
și apoi decomprimăm arhiva
unzip curs-05-demo.zip
și accesăm directorul rezultat în urma decomprimării
cd curs-05-demo/
Acum putem parcurge secțiunile cu demo-uri de mai jos.
Ca să aflăm informații despre memoria RAM (fizică) disponibilă pe sistem folosim comanda
free -m
Rezultatul afișat este în megaocteți.
Altă variantă este consultarea fișierului /proc/meminfo:
cat /proc/meminfo
Spațiul de adresare disponibil îl putem afla prin consultarea fișierului /proc/cpuinfo:
cat /proc/cpuinfo | grep 'address sizes'
Ni se vor afișa informații despre spațiul adresabil fizic și cel virtual. În general, la sistemele cu arhitectură x86_64, deși registrele sunt pe 64 de biți, spațiul adresabil virtual este de 48 de biți.
Pentru a afla informații desre memoria cache a sistemului, folosim comanda
lscpu
 și urmărim liniile care conțin cuvântul cache. Sau folosim comanda
getconf -a | grep 'CACHE'
De obicei avem mai multe niveluri de memorie cache. Primul nivel conține în general un cache pentru date și unul pentru instrucțiuni.
Pentru a afla dimensiunea paginii sistemului folosim comanda
getconf PAGE_SIZE
Programatic, astfel de informații pot fi determinate prin intermediul apelului sysconf. O implementare succintă se găsește în subdirectorul system-memory/. În fișierul system-memory.c folosim apelul sysconf pentru a afla dimensiunea paginii sistemului, spațiul de memorie, informații despre memoria cache. Pentru a folosi programul, îl compilăm și îl rulăm:
make ./system-memory
Spațiul de adresă al unui proces poate fi vizualizat folosind comanda pmap. De exemplu, dacă dorim să vizualizăm spațiul de adresă al procesului curent folosim comanda
pmap $$
Spațiul de adresă al unui proces cuprinde zona de cod/text (marcată r-x), zone de date (marcate r-- și rw-), biblioteci partajate, heap, stivă.
Spațiul de adresă al procesului este modificat dinamic (la runtime) prin alocare și dezalocare de memorie. Pentru a urmări modul în care este alterat spațiul de adresă al procesului la alocare și dezalocare folosim programul din subdirectorul address-space/.
În fișierul address-space.c alocăm și dezalocăm memorie folosind stiva (la un apel de funcție), apelurile malloc și free, respectiv apelurile mmap și munmap. Înaintea executării unui pas programul așteaptă 5 secunde, timp în care putem urmări evoluția spațiului de adresă.
Pentru a urmări evoluția programului avem nevoie de două console. Într-o consolă compilăm și rulăm programul, iar în alta verificăm funcționalitatea sa folosind pmap.
Pentru acesta în prima consolă compilăm și rulăm:
make ./address-space
Apoi, în cealaltă consolă rulăm periodic comanda:
pmap $(pidof address-space)
Observăm cum se modifică dimensiunile diverselor regiuni după alocare. Stiva nu se modifică; stiva este deja alocată iar spațiul ocupat de buffer nu conduce la alterarea stivei. Pentru malloc/free și mmap/munmap se alocă/eliberează dimensiunea cerută în conformitate cu apelul.
Deși un apel de genul malloc permite alocare fină de memorie (de nivelul octeților), în spate sistemul de operare și hardware-ul alocă memorie la nivel de pagină. Un apel de alocare a memoriei va aloca mai mult spațiu pentru a permite viitoare alocări.
Pentru a verifica acest lucru folosim subdirectorul allocation-granularity/. Fișierul allocation-granularity.c este un program care primește ca argument dimensiunea care să fie transmisă apelului malloc și apoi așpteaptă 5 secunde înainte și după pentru a putea urmări efectul acestei alocări asupra spațiului de adresă, după care procesul este închis.
Vom folosi două console: pe o consolă vom rula programul iar pe alta vom investiga spațiul de adresă aferent. Pentru aceasta pe prima consolă vom compila și vom rula procesul:
make ./allocation-granularity 1
în vreme ce pe a doua consolă vom consulta spațiul de adresă al procesului:
pmap $(pidof allocation-granularity)
Prima comandă alocă un singur octet în mod dinamic în cadrul spațiului de adresă. Ultima comandă o vom rula de mai multe ori pentru a verifica modul în care se modifică spațiul de adresă al procesului. Vedem că la o simplă alocare de 1 octet se alocă o zonă mai mare în spațiul de adresă al procesului, conform modului intern de lucru al apelului de bibliotecă malloc.
Pentru a afla informații despre TLB instalăm pachetul cpuid. Pe un sistem Debian-based folosim comanda
apt-get install cpuid
Ca să determinăm informații despre TLB folosim comanda
cpuid | grep TLB
Dacă vrem să urmărim numărul de miss-uri pentru TLB putem folosi perf. De exemplu, pentru a urmări TLB miss-urile într-un interval de 10 secunde la nivelul sistemului folosim comanda
sudo perf stat -e iTLB-load-misses -a sleep 10
TLB miss-urile cresc în momentul schimbării spațiului de adresă, adică la planificarea proceselor. Dacă avem multe schimbări de spațiu de adresă între procese atunci numărul de TLB miss-uri va crește. Pentru a verifica acest lucru, din arhiva laboratorului 4, din subdirectorul nice/ rulăm scriptul start-all (după ce am compilat în prealabil executabilul cpu). După ce am rulat scriptul folosim o altă consolă pentru a măsura numărul de TLB miss-uri, folosind aceeași comandă ca mai sus:
sudo perf stat -e iTLB-load-misses -a sleep 10
Observăm un număr semnificativ mai mare de TLB miss-uri datorat numeroaselor schimbări de context ce au loc între procesele pornite de scriptul ''start-all'.