Reputation: 77
I'm not sure if this question is on-topic (and I apologize if it's not), but I wonder how memory management can be accomplished when creating an operating system. My understanding is:
This sounds like an oxymoron. How can a memory manager be written if the tool to write it needs a memory manager in the first place? Must it be done in assembly?
Upvotes: 2
Views: 214
Reputation: 21607
An operating system needs to manage memory for both itself (kernel) and users.
You seem to be asking about user memory management. That is done by managing pages allocated to the process. The stack is managed by assigning pages process.
Heap memory management (like malloc) is done in two parts. For the operating system kernel provides system services to map pages to the process. Second, the library manages one or more pools of memory creates within those pages.
Upvotes: 0
Reputation: 16156
C does not require managed memory. You are probably thinking of the malloc
library function, but this is just a function (though standardised to be available to user programs).
An easy to implemented memory allocation scheme is the following:
char * free_space;
void * kmalloc(size_t s) {
char * block = free_space;
free_space += s;
return block;
}
// free not possible
The pointer free_space
must be set during initialisation to the start of a known free area of memory. This might be given by the boot loader through the multiboot information.
A more complex example can be found in this code for a kernel that I wrote a long time ago.
Generally memory management is divided into multiple phases:
During initialisation a simple scheme like the one above helps setting up a more complex allocator like the one I wrote.
This allocator only provides blocks of a fixed size (4Kb usually, sometimes also multiples of this size).
These blocks are requested from a higher level allocator when it's memory pool gets filled up. This allocator is the one you normally call via malloc
. A prominent example is Doug Lea's dlmalloc.
Concerning the stack: The compiled code does the increment and decrement of the stack pointer. But obviously it has to be set to some available space before. For the kernel, during initialisation, you normally set it just somewhere you know to be free memory, for example a part of your binary. This is done in assembly:
lea esp, kstack
; ...
call startup_kernel
; ...
[SECTION .bss]
resb 32768
kstack:
Startup code in assembly from the aforementioned kernel
For processes later on you allocate a frame or more using the in-kernel allocator and set the stack to point to it's end (in case of a decrementing stack). This example from another kernel shows what is done to setup the stack for a new process (this is highly depended on the actual kernel / task switch code). (In this case there is no dynamically allocated memory as it was used in a embedded scenario).
Upvotes: 2