Programarea calculatoarelor 2 - Laborator 12
Implementați funcțiile void *alloc(size_t size) și
void release(void *ptr) pentru gestionarea dinamică a memoriei.
Acestea vor funcționa ca și malloc, respectiv free,
dar lucrând cu memoria dintr-un tablou declarat static în program (de
exemplu de 4MB = 2^22 octeți). Memoria va fi gestionată în blocuri de
dimensiuni precizate, după cum urmează:
- dimensiunile blocurilor sunt puteri ale lui 2. (Dacă doriți, puteți
însă implementa un sistem buddy de ordin >= 1, de ex. Fibonacci).
- fiecare bloc conține un câmp pentru lungime, și un bit care indică
dacă blocul e alocat sau liber
- în plus, blocurile libere conțin câmpuri pentru predecesor și succesor,
păstrându-se câte o listă dublu înlănțuită pentru fiecare dimensiune.
- blocurile au o dimensiune minimă suficientă pentru a conține câmpurile
descrise mai sus
- inițial, întreg tabloul e un unic bloc liber.
La o solicitare, se va aloca un bloc de cea mai mică dimensiune acoperitoare
dintre cele permise (ținând cont și de faptul că trebuie să ramână rezervate
câmpurile care indică lungimea și ocuparea). Dacă nu există un astfel de
bloc disponibil, se va fragmenta (eventual succesiv) un bloc acoperitor,
cât mai mic, păstrându-se fragmentele rămase ca blocuri libere.
Testați programul alternând la întâmplare alocări de dimensiuni aleatoare
cu dealocări, de asemenea aleatoare, dintre blocurile alocate deja.
Observații:
- Pentru a economisi spațiu, în loc de lungimea blocului se poate reține
numărul de ordine din secvența de lungimi posibile. De exemplu, pentru
lungimi 8, 16, 32, ... reținem 0, 1, 2, etc. La fel, pentru legăturile
predecesor și succesor se poate ține cont de faptul că adresele blocurilor
sunt multipli ale dimensiunii minime. În acest fel, 8 octeți sunt suficienți
pentru un spațiu de adrese de 32 de biți: 5 biți pentru <= 32 de lungimi
posibile, un bit pentru ocupare, și 2 * (32-3) biti pentru legăturile
înainte și înapoi). Dintre acesția, doar un octet (cu dimensiunea și
bitul de ocupare) e spațiul suplimentar folosit într-un bloc ocupat.
- Pentru compactare la eliberarea blocurilor, se poate determina simplu
care e blocul "pereche" care trebuie testat: dacă blocul eliberat are
dimensiunea 2^i, și adresa lui (în cadrul tabloului) e un multiplu par de 2^i,
perechea sa e vecinul următor de dimensiune 2^i; daca adresa e multiplu impar
de 2^i, perechea sa e vecinul anterior.
Marius Minea
Last modified: Wed Jan 7 00:44:21 EET 2004