Teme:Memorie virtuala

Termen de predare: Miercuri, 6 mai 2009, ora 23:59:59 (2009-05-06)

Enunt
Să se implementeze sub forma unei biblioteci un "swapper &amp; demand pager" pentru o zonă de memorie virtuală de dimensiune fixă.
 * Memoria virtuală va fi reprezentată de o zonă de memorie din spațiul de adresă al procesului și va avea virt_pages pagini disponibile.
 * Memoria fizică (= memoria RAM) va fi simulată de un fișier și va avea phys_pages pagini disponibile.
 * Pentru swapping se va folosi al doilea fișier, care va avea virt_pages pagini disponibile.

Recomandare: Paginile de memorie virtuală (din spațiul de adresă al procesului) se pot mapa individual direct peste fișierul de RAM folosind funcțiile mmap (Linux) și MapViewOfFileEx (Windows).

Biblioteca trebuie să creeze mapări între paginile virtuale și paginile fizice (din RAM) și să ofere următoarele funcții, prezentate în fișierul header tema-mv.h.

Linux

Windows

In cadrul functiei vinit va avea loc, de asemenea, crearea fisierelor ce reprezinta ram-ul si swap-ul si initializarea handler-elor de semnale, respectiv a vectorilor de exceptie.
 * Functia vinit va intoarce un pointer catre o zona de memorie din spatiul de adresa al procesului; zona obtinuta reprezinta spatiul de memorie virtuala pe care il poate accesa procesul, pointer-ul intors fiind, astfel, adresa de inceput a memoriei virtuale.


 * Functia vend realizeaza cleanup: demaparea zonei de memorie virtuala cumulata cu inchiderea fisierelor ce reprezinta ram-ul si swap-ul si resetarea handler-ului de semnal/vectorului de exceptii. vend returnează 0 în caz de succes și -1 în cazul unei erori. Singura eroare testată este dacă se apeleaza vend</tt> când biblioteca de memorie virtuală nu a fost inițializată în prealabil în mod corect (nu s-a apelat vinit</tt> sau cel mai recent vinit</tt> a returnat NULL</tt>).


 * Functiile get_ram_fd</tt>, respectiv get_swap_fd</tt> intorc descriptorii fisierelor asociate memoriei fizice si swap-ului.


 * Functia ram_sync</tt> realizeaza sincronizarea intre datele reprezentate in memoria virtuala si fisierul ce simuleaza memorie RAM. Functia are rolul de efectuare a unui flush a datelor din memoria virtuala astfel incat acestea sa se gaseasca in fisierul ce reprezinta memoria RAM. ram_sync</tt> va fi implementată folosind un apel msync</tt>.

Functiile pe Windows realizeaza aceleasi lucruri, doar ca sunt denumite diferit.

Precizări generale

 * Funcția vinit</tt>/VirtualInit</tt> va rezerva virt_pages în memoria virtuală a procesului. Paginile din acest spațiu nu trebuie sa fie prezente și în memoria RAM după apelul funcției vinit</tt>/VirtualInit</tt>.


 * Paginile vor fi create în memoria RAM doar atunci când programul le accesează (on demand paging). La crearea paginilor, acestea trebuie să aibă doar bytes 0 (doar zero-uri).


 * Exista predefinit in fisierul header o valoare maxima a numarului de pagini virtuale, respectiv fizice care pot fi transmise vinit</tt>/VirtualInit</tt>. De asemenea, se impune conditia ca paginile virtuale sa fie in numar mai mare ca paginile fizice. Daca aceste conditii nu au loc, functia intoarce NULL.


 * Daca nu mai sunt pagini fizice libere, biblioteca trebuie sa evacueze o pagina fizica in swap. Paginile din swap trebuie aduse in memoria fizica atunci cand ele sunt accesate (precum in realitate, memoria virtuala lucreaza doar cu memoria fizica, nu cu swap-ul).


 * Pentru o pagina care rezida in memoria fizica va trebui sa faceti deosebirea intre o pagina care a fost modificata (dirty) si una care nu a fost modificata. Daca o pagina nu a fost modificata atunci, in momentul inlocuirii, ea nu va mai fi inlocuita in swap (nu se va face copiere). Pentru usurinta in testare, acest lucru ramane valabil si la paginile care sunt initial read-only.


 * Pentru a implementa logica de "on demand pagining" si cea de "swapping", trebuie sa interceptati page-fault-urile produse in momentul unui acces invalid la o zona de memorie. La interceptarea page-fault-urilor, folositi modificari succesive ale drepturilor paginilor pentru a implementa logica temei. La inceput, paginile nu au nici un drept (PROT_NONE/PAGE_NOACCESS).


 * Nu se impune nici o constrangere legata de algoritmul de evacuare a paginilor in swap. Puteti folosi aceeasi pagina, sau o pagina aleasa aleator, sau un algoritm cunoscut (FIFO, LRU, etc.)


 * Modificarile realizate asupra memoriei virtuale nu se reflecta imediat in fisierul asociat memoriei RAM (memoria RAM fiind mapata peste acest fisier). De aceea, atunci cand se doreste verificarea memoriei RAM (in teste), trebuie facuta sincronizarea paginilor din memorie cu fisierul. Nu este nevoie sa faceti sincronizarea intre memorie si fisier. Acest lucru se va realiza in momentul in care testele apeleaza functia ram_sync</tt> pusa la dispozitie de biblioteca.


 * Actualizarea inversa, de la RAM la memoria virtuala se realizeaza in momentul copierii unei pagini din swap in RAM, in cazul unui page-fault (cand pagina dorita se afla in swap).


 * Nu se impune nici o restrictie de nume asupra fisierelor ce reprezinta memoria RAM, respectiv swap-ul. Programul de test utilizeaza descriptorul, respectiv handle-ul asociat fisierelor prin intermediul functiilor <tt>get_ram_fd</tt> si <tt>get_swap_fd</tt>.


 * Pentru mai multe informatii despre demand paging si swapping, consultati Cursul 7 sau cititi capitolul de memorie virtuala din "Modern Operating Systems".

Imagine
Imaginea de mai jos prezintă "fluxul" paginilor prin memorie și o posibilă stare la un moment dat.



Aceasta imagine este doar principială și nu reprezinta o stare în care se poate găsi memoria în timpul sau ca urmare a execuției testelor.

Precizari Windows
Pentru ca pe Windows, nu se pot crea (usor) pagini virtuale multiple de pagini ale sistemului (ci multiplu de 64 K) s-a definit variabila

static DWORD pageSize = 0x10000;

care va fi folosita pentru a specifica dimensiunea unei pagini.

Tema se va rezolva folosind doar functii Win32. Se pot folosi de asemenea si functiile de formatare <tt>printf, scanf</tt>, functiile de alocare de memorie <tt> malloc, free</tt> si functiile de manipulare a sirurilor de caractere (<tt>strcat</tt>, <tt>strdup</tt>, etc.)

Pentru partea de I/O si procese se vor folosi doar functii Win32. De exemplu, functiile <tt>open</tt>, <tt>read</tt>, <tt>write</tt>, <tt>close</tt> nu trebuie folosite, in locul acestor trebuind sa folositi <tt>CreateFile</tt>, <tt>ReadFile</tt>, <tt>WriteFile</tt>, <tt>CloseHandle</tt>.

Pentru gestiunea memoriei virtuale folositi functiile <tt>VirtualAlloc/VirtualFree/VirtualProtect</tt>.

Pentru interceptarea acceselor invalide la zone de memorie (general protection fault) folositi apelurile <tt>AddVectoredExceptionHandler/RemoveVectoredExceptionHandler.</tt>

În cazul funcţiei VirtualEnd, se returnează FALSE în caz de eroare şi TRUE la succes.

Precizari Linux
Tema se va rezolva folosind doar functii POSIX. Se pot folosi de asemenea si functiile de formatare <tt>printf, scanf</tt>, functiile de alocare de memorie <tt> malloc, free</tt> si functiile de manipulare a sirurilor de caractere (<tt>strcat</tt>, <tt>strdup</tt>, etc.)

Pentru partea de I/O si procese se vor folosi doar functii POSIX. De exemplu, functiile <tt>fopen</tt>, <tt>fread</tt>, <tt>fwrite</tt>, <tt>fclose</tt> nu trebuie folosite, in locul acestor trebuind sa folositi <tt>open</tt>, <tt>read</tt>, <tt>write</tt>, <tt>close</tt>.

Pentru gestiunea memoriei virtuale folositi functiile <tt>mmap/munmap/mprotect</tt>.

Pentru interceptarea accesului invalid la o zona de memorie va trebui sa interceptati semnalul <tt>SIGSEGV</tt> folosind apeluri din familia <tt>sigaction</tt>.

Dimensiunea paginii de memorie virtuala o aflati cu ajutorul functiei <tt>getpagesize</tt>.

Testare
Corectare a temelor se va face automat cu ajutorul testelor publice:
 * Linux - test-mv-lin.zip
 * Windows - test-mv-win.zip

In urma compilarii temei trebuie sa rezulte o biblioteca shared-object (Linux) denumita libvm.so sau o biblioteca dll (Windows) denumita libvm.dll. Functiile care sunt exportate de biblioteca se gasesc in fisierul header tema-mv.h. Acesta trebuie inclus in arhiva in care se trimite tema.

O tema care trece toate testele poate lua maxim nota 10. Pot exista penalizari in cazul in care apar warning-uri sau intarzieri, sau daca nu se respecta unele criterii cum sunt cele mentionate mai jos:


 * -0.1 - Makefile necorespunzator
 * -0.1 - README necorespunzator
 * -0.4 - cod neingrijit (indentare inexistenta sau necorespunzatoare, surse necomentate)
 * -0.4 - neeliberare resurse, neverificare conditii de eroare, folosire necorespunzatoare a functiilor din API

In cazul in care se trec numai anumite teste punctarea se va face proportional cu numarul total de teste. Cazuri speciale sunt testele de tip check si clean (in numar de 11): acestea au o valoare de 0.5p fiecare Un test poate fi depunctat daca acesta reuseste sa fie valid ("Passed") dar implementarea este invalida.

Întrebări
Pentru întrebări sau nelămuriri legată de temă puteți căuta, consulta sau [mailto:so@cursuri.cs.pub.ro trimite un mail pe] lista de discuții (trebuie să fiți înregistrați).