OS-DEV: malloc/free - the secrets revealed
back
The average programmer uses them with almost no thought about the background. He just orders memory during runtime of his program
and gives it back to the system - so it seems to him. The OS Developer of such a library has of course other things to take care of: how to split the
memory, the Operating System sets aside for especially this purpose, in small and smaller chunks as the programmer needs them. To manage
this region, also called Heap, in the standard c library, a set of functions is known: malloc(), free(). They hand out resp. take back memory chunks.
malloc and free aren't difficult to develop nor to implement. You just need to keep in mind: you assign the malloc library an adress to work with,
which the OS has to map into the process adress space. It is up to you to decide, where to place it.
Then, you'll need a structure to keep some bookkeeping data: let's call it chunk_t. Below, you can see a layout of chunk_t:
Upon initializing the malloc library (at the first usage of malloc() is recommended for this operation) you place some data at the beginning of the heap:
chunk_t *used_head,*used_tail; chunk_t *free_head,*free_tail; you have to place them by hand, ie incrementing the actual position counter by
sizeof(chunk_t), casting the adress to chunk_t and placing the initial values there. It looks like this, assuming, the start of the heap is 0xc0500000.
//definitions!
typedef struct MEM{
adresse_t *block_adresse;
uint_t block_length;
struct mem *next;
} mem_t;
typedef struct mem_list{
mem_t *head; //um schnell durch das speicherblock-array zu marschieren
mem_t *tail;
} mem_list_t;
//declaration of variable used blocks:
mem_list_t used_blocks;
//declaration of variable free blocks:
mem_list_t free_blocks;
//somewhere, the lists are initialized, say in a function 'malloc_init();'
free_blocks.head=(mem_t *)0xc0500000;
free_blocks.tail=free_blocks.head;
free_blocks.head->next=NULL;
used_blocks.head=(mem_t *)0xc0500060;
used_blocks.ende=used_blocks.head;
used_blocks.head->next=NULL;
Having done all this initialization stuff and knowing, what datatypes we need, we can proceed to what to do next:
Allocating a memory area for further use.
This can be done as follows:
- 1. traverse the list of Free Blocks for one whose lenght >= requested length of memory.
- 2. if found a place: detach it from the List of free blocks and attach it to the used blocks list tail.
- 3. if not found a place: create a new place and attach it to the used blocks list tail:
cast the current free address at the end of used heap to chunk_t *. add sizeof(chunk_t) to it. then assign the resulting sum to the address-field of chunk_t.
add the length of the requested block to current free address so it points to the bottom of used heap.
- 4. return the acquired address to the caller.
Now, lets have a look at how to free an allocated memory region:
basically, it's nothing more than taking the adress to be freed, traverse the list of used blocks, remove the block in question and attach it to the
list of free blocks. Now, look at it in Detail:
- 1. traverse the list of used blocks. filter: block->address==address_to_be_freed.
- 2. if found the block: detach it from the list of used blocks and attach it to the list of free blocks tail.
look at the illustration above to see, how a heap can look like after several allocations/deallocations of memory chunks:
You see, it is not as grim as it looks like on the first glance. What you will of course need is a decent knowledge about how to handle linked lists.
Think further. What might be useful? What can happen? How does the Operating System deal out Memory?
- Heap Memory runs out: call to morecore gives more of it. The operating system widens the heap space. Where to put it? Think hard. *gg*
- Coalescing free blocks at the end of the heap, if they are all adjacent. Occasionally hand memory back to the OS, if a page gets free.
- statistics: how many chunks are free? How many chunks are used?
- garbage collection: is there some unreferenced chunk, which the program doesn't use any more?
back