The OS is in long mode and has paging enabled.
For memory management I have looked at several examples of custom malloc functions but there is a common issue, they all use sbrk. Since I compile with -ffreestanding, I don't have access to sbrk. So, how can I allocate memory without using sbrk?
I'm new to OS development so I apologize in advance.
Freestanding c memory manager without sbrk()
-
- Member
- Posts: 25
- Joined: Tue Mar 09, 2021 9:31 pm
- Libera.chat IRC: isaiah0311
Re: Freestanding c memory manager without sbrk()
Implement your own version of sbrk?
Re: Freestanding c memory manager without sbrk()
malloc() is several levels too deep already. First you need a physical memory manager. Your boot environment tells you where the RAM is, and you need a function that returns free physical addresses and marks them as used at the same time. Common solutions to this include free lists, a stack, and bitmaps.
You will also need a virtual memory manager. That is, you will need some kind of virtual memory layout for kernel space. In Long Mode you have so much virtual memory that it might be sufficient to just use a High Water Mark allocator for virtual memory.
Finally, you will need code to connect the two. Set up page tables, set up Virtual Memory Areas (VMAs), make it possible to resolve page faults.
Once you have all of these, you can start to implement a general purpose malloc(), because now you can allocate whole pages. malloc() is more about dividing the memory down into smaller chunks such that you don't waste too much.
If you've never thought about any of the above, now is the time. This is where you have to start designing, and not blindly following tutorials.
You will also need a virtual memory manager. That is, you will need some kind of virtual memory layout for kernel space. In Long Mode you have so much virtual memory that it might be sufficient to just use a High Water Mark allocator for virtual memory.
Finally, you will need code to connect the two. Set up page tables, set up Virtual Memory Areas (VMAs), make it possible to resolve page faults.
Once you have all of these, you can start to implement a general purpose malloc(), because now you can allocate whole pages. malloc() is more about dividing the memory down into smaller chunks such that you don't waste too much.
If you've never thought about any of the above, now is the time. This is where you have to start designing, and not blindly following tutorials.
Carpe diem!
-
- Member
- Posts: 25
- Joined: Tue Mar 09, 2021 9:31 pm
- Libera.chat IRC: isaiah0311
Re: Freestanding c memory manager without sbrk()
I didn't think it was going to be that easy, it was. Thank you. I found a simple sbrk online and implemented it. It seems to be working now.iansjack wrote:Implement your own version of sbrk?
So right now I have a virtual memory manager (or at least I think), which uses a union to hold a struct of header data and then a 16 byte stub for alignment. This is similar to the flat list example on the page frame allocation page on the wiki.nullplan wrote:malloc() is several levels too deep already. First you need a physical memory manager. Your boot environment tells you where the RAM is, and you need a function that returns free physical addresses and marks them as used at the same time. Common solutions to this include free lists, a stack, and bitmaps.
You will also need a virtual memory manager. That is, you will need some kind of virtual memory layout for kernel space. In Long Mode you have so much virtual memory that it might be sufficient to just use a High Water Mark allocator for virtual memory.
Finally, you will need code to connect the two. Set up page tables, set up Virtual Memory Areas (VMAs), make it possible to resolve page faults.
As for the physical manager, I'm not so sure if my code does that. I have a char global_memory[20000] variable that gets used in sbrk. I don't know if this is what you mean?
Code: Select all
char global_memory[20000] = { 0 };
void* sbrk(int increment) {
char* p_break = global_memory;
char* const limit = global_memory + 20000;
char* const original = p_break;
if (increment < global_memory - p_break || increment >= limit - p_break)
return (void*) -1;
p_break += increment;
return original;
}
Re: Freestanding c memory manager without sbrk()
I think defining where kernel memory starts & ends + implementing the page fault handler will do. At least if you let the page fault handler fix the page directory and ptr levels too. You could allocate those on startup too, but I think letting the pagefault handler do it is more attractive. If you setup these pages as zeros, then you can assume that unallocated pages are zero entries, and then there is no need for setting up VMAs. When malloc() tries to access something in it's area, you simply let the pagefault handler allocate a physical page and set it up as kernel read&write. Also note that malloc() should not zero all of the area it uses, as this would allocate all the physical memory. Rather, it should avoid touching areas it doesn't do allocations in.nullplan wrote: Finally, you will need code to connect the two. Set up page tables, set up Virtual Memory Areas (VMAs), make it possible to resolve page faults.
Also, I think a kernel also should have a 4k aligned (page table entry) allocation method. And probably a more efficient method to allocate many entries of the same size.
Re: Freestanding c memory manager without sbrk()
@isaiah0311: Your code actually has a major bug. The variable p_break must be a global variable. Else, every allocation will overwrite the last one!
Also, that global_memory array is not going to work for very long. You see, your kernel will have way more then 20000 bytes it allocates. You need a way of being even more dynamic. Have a look at https://wiki.osdev.org/Brendan%27s_Memo ... ment_Guide. This should give some direction.
Also, that global_memory array is not going to work for very long. You see, your kernel will have way more then 20000 bytes it allocates. You need a way of being even more dynamic. Have a look at https://wiki.osdev.org/Brendan%27s_Memo ... ment_Guide. This should give some direction.