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'.