Table of Contents

Virtual Memory Allocator

Responsabili

Actualizări

Obiective

Introducere

Studenții de anul întâi au aflat de la colegii mai mari de o materie interesantă pe care urmează să o aibă în anul 2, faimoasa Observarea Sistemelor de Operare (cu acronimul OSO). Fiind curioși, au început deja investigația, și pe lângă meme-uri, debate-uri și cereri de prelungire a deadline-urilor temelor, au găsit și concepte inedite, precum memoria virtuală.

Bineînțeles, studenții sunt niște ființe deloc leneșe, așa că s-au apucat deja de prima temă, un alocator de memorie virtuală, pe care vi-l arată și vouă, extaziați. Scopul vostru este să le mai micșorați avântul și să implementați împreună cu frații voștrii de suferință această funcționalitate a sistemului de operare, folosind exclusiv liste dublu înlănțuite. Pe parcurs, nu veți avea nevoie de cunoștințe de Sisteme de Operare, dar, dacă într-adevăr, vă pasionează subiectul, vizitați pagina oficială a cursului.

Cerință

Un alocator de memorie are rolul de a rezerva memorie, la nivel de bibliotecă, tradițional prin apeluri precum malloc() sau calloc(). Acestea marchează ca fiind folosite anumite zone de memorie dintr-un pool de bytes prealocat, numit arenă. De asemenea, alocatorul de memorie se ocupă și cu eliberarea zonelor rezervate, apelul de bibliotecă aferent fiind free().

Alocatorul de memorie virtuală pe care îl veți implementa va avea următoarele funcționalități (sau API):

 Img 1

Astfel, lista dublu înlănțuită principală reține block-urile alocate, pe când listele dublu înlănțuite din aceasta rețin miniblock-urile consecutive. O structură posibilă pentru block ar arăta în felul următor:

{
   uint64_t start_address; // adresa de început a zonei, un indice din arenă
   size_t size; // dimensiunea totală a zonei, suma size-urilor miniblock-urilor
   void* miniblock_list; // lista de miniblock-uri adiacente
} block_t;
 

O structură posibilă pentru miniblock ar arăta în felul următor:

{
   uint64_t start_address; // adresa de început a zonei, un indice din arenă
   size_t size; // size-ul miniblock-ului
   uint8_t perm; // permisiunile asociate zonei, by default RW-
   void* rw_buffer; // buffer-ul de date, folosit pentru opearțiile de read() și write()
} miniblock_t;

Comenzi posibile (40p)

Input-ul este oferit de la stdin, iar output-ul la stdout, respectând formatul următor:

Dacă nu ați implementat bonusul, permisiunile miniblock-urilor vor fi mereu RW-!

Formatul de afișare pentru PMAP este următorul:

Total memory: x
Free memory: y
Number of allocated blocks: z
Number of allocated miniblocks: q

Block 1 begin
Zone: address1 - address2
Miniblock 1:\t\taddress1\t\t-\t\taddress1a\t\t| permissions
Miniblock 2:\t\taddress1a\t\t-\t\taddress1b\t\t| permissions
.
.
.
Miniblock n:\t\taddress1x\t\t-\t\taddress2\t\t| permissions
Block 1 end

Block 2 begin
Zone: address3 - address4
Miniblock 1:\t\taddress3\t\t-\t\taddress3a\t\t| permissions
Miniblock 2:\t\taddress3a\t\t-\t\taddress3b\t\t| permissions
.
.
.
Miniblock m:\t\taddress3y\t\t-\t\taddress4\t\t| permissions
Block 2 end
.
.
.
Block z begin
.
.
.
Block z end

Tratarea erorilor (40p)

La primirea comenzilor, pot apărea erori de input. Pe acestea, voi trebuie să le tratați corespunzător, prin afișarea unui mesaj sugestiv:

Bonus (20p)

Exemplu

Fie input-ul:

ALLOC_ARENA 65536
ALLOC_BLOCK 4096 10
ALLOC_BLOCK 12288 10
ALLOC_BLOCK 12308 10
PMAP
ALLOC_BLOCK 12298 10
PMAP
WRITE 4096 26 Observ sisteme de operare
READ 4096 14
FREE_BLOCK 12298
MPROTECT 12308 PROT_NONE
WRITE 12308 24 Sper să nu iau SEGFAULT
PMAP
DEALLOC_ARENA

Output-ul corespunzător acestei secvențe de operații este:

Total memory: 0x10000 bytes
Free memory: 0xFFE2 bytes
Number of allocated blocks: 3
Number of allocated miniblocks: 3

Block 1 begin
Zone: 0x1000 - 0x100A
Miniblock 1:        0x1000      -       0x100A      | RW-
Block 1 end

Block 2 begin
Zone: 0x3000 - 0x300A
Miniblock 1:        0x3000      -       0x300A      | RW-
Block 2 end

Block 3 begin
Zone: 0x3014 - 0x301E
Miniblock 1:        0x3014      -       0x301E      | RW-
Block 3 end
Total memory: 0x10000 bytes
Free memory: 0xFFD8 bytes
Number of allocated blocks: 2
Number of allocated miniblocks: 4

Block 1 begin
Zone: 0x1000 - 0x100A
Miniblock 1:        0x1000      -       0x100A      | RW-
Block 1 end

Block 2 begin
Zone: 0x3000 - 0x301E
Miniblock 1:        0x3000      -       0x300A      | RW-
Miniblock 2:        0x300A      -       0x3014      | RW-
Miniblock 3:        0x3014      -       0x301E      | RW-
Block 2 end
Warning: size was bigger than the block size. Writing 10 characters.
Warning: size was bigger than the block size. Reading 10 characters.
Observ sis
Invalid permissions for write.
Total memory: 0x10000 bytes
Free memory: 0xFFE2 bytes
Number of allocated blocks: 3
Number of allocated miniblocks: 3

Block 1 begin
Zone: 0x1000 - 0x100A
Miniblock 1:        0x1000      -       0x100A      | RW-
Block 1 end

Block 2 begin
Zone: 0x3000 - 0x300A
Miniblock 1:        0x3000      -       0x300A      | RW-
Block 2 end

Block 3 begin
Zone: 0x3014 - 0x301E
Miniblock 1:        0x3014      -       0x301E      | ---
Block 3 end

Acest exemplu corespunde figurii de mai sus. Asigurați-vă că urmăriți exemplul și figura în paralel, pentru o mai bună înțelegere a comenzilor. Astfel:

README (10p)

Coding style (10p)

Mențiuni

  • O structură de date generică are rolul de a nu duplica (pe cât posibil) cod permițând adăugarea în cadrul ei a oricărui tip de date. (hint: void *)
  • Exemplu: Vedeți în cadrul scheletului de lab unde a trebuit să implementați exact această situație. (hint: data_size)

  • Este obligatorie construirea unei implementări care folosește conceptul de listă în listă.
  • Orice tentativă de alocare a unui vector liniar, contiguu și de simulare a operațiilor aplicate arenei pe acesta este interzisă. Arena există doar la nivel conceptual, task-urile temei aplicându-se pe lista dublu înlănțuită de block-uri, respectiv miniblock-uri.
  • Nerespectarea acestor constrângeri va conduce la notarea temei cu 0 puncte.

Checker

Scheletul poate fi găsit aici.

Temele vor fi trimise pe vmchecker. Atenție! Temele trebuie trimise în secțiunea Structuri de Date (CA).

Arhiva trebuie să conțină: