How can I improve my OS code? What direction should I take t
Posted: Mon Oct 13, 2014 6:42 pm
This is a very broad question, and is more of a request for feedback. I'm in the process of writing my own operating system, and have successfully implemented a physical memory manager. You can see my code here:
https://github.com/PSanf2/POS_C9
I believe my memory manager implementation will allow me to move into paging. I would like to know where I could make improvements, or where I'm making major mistakes, before I go further. Because this is my first time writing an operating system I'm learning as I go, and wish to avoid a mistake hindering my progress later.
With my OS I'm loading the kernel at the 1M mark, and using everything after the kernel for free memory. I'm not touching anything before the kernel, and writing off the wasted megabyte as "GRUB space." I've read about having your kernel set up in the "higher half" starting at the 3G address, and then using all of the memory below that, and after the kernel, for the paging. I understand that this isn't a requirement, but how much more difficult am I making things on myself by loading my kernel in the "lower half?" I'm writing my OS for a 32-bit system, and believe that the higher half setup has something to do with making my OS compatible with other programs that wish to run at lower memory addresses. Is this correct, or am I worrying about nothing? My memory manager is currently set up to start allocating memory from the first address after the kernel, and relies on external values from the linker and GRUB to determine the proper place to start. Should I rework my OS to use a higher half kernel, and have the memory manager start allocating memory from address 0, or 1M? Once the kernel is loaded can I reclaim the "GRUB space," assuming I save the multiboot header information?
For my memory manager I'm using a doubly linked list to keep track of free memory. I'm doing this for the sake of simplicity, and aware that other data structures will provide a better algorithmic complexity. GRUB provides information telling me where my kernel ends, and how much memory I have available. Each node on the list has a "header" which I use to keep track of memory. The header on the first node is 256 bytes, and the header on each subsequent node is 64 bytes. The headers contain information telling me where the previous and next nodes in memory are, where the free memory associated with the node starts, and the size of the memory that the node contains. Allocating memory involves splitting an adequately sized node of free memory, removing the allocated node from the list, and returning a pointer to the first address of the allocated memory. The header always stays with the memory, even when it's removed from the free memory list. When I free memory, I give a function a pointer to the first address of allocated memory, back it up the proper amount to get to the header, and then put the node back on the list. From there I go over the list, and compact adjacent nodes. Basically, I have this: http://wiki.osdev.org/images/a/a4/Flat_list.png
Will I be able to use my memory manager to successfully implement paging? I understand that when I enable paging the way I use memory addresses should change. Is this an entirely logical process the programmer handles, where I translate the page index and offset into a physical address, or is the translation handled by the Memory Management Unit? I understand that to implement paging I'll need to define a page directory data structure at a 4K aligned address. I plan on implementing a new memory allocation function that will ensure the address returned is aligned properly by splitting an unallocated node at the proper place. My page directory will have 1024, 32-bit, pointers to page tables, totaling 4K in size. I'm thinking that I'll allocate 4K of memory at a properly aligned address, and that the pointer I get back will be what I give to cr3 for my page directory. The page tables will each contain 1024, 32-bit, pointers to 4K sections of memory. I'm shooting for this: http://wiki.osdev.org/images/7/77/Paging_Structure.gif When creating the page table entries, do I need to allocate the 4K memory needed by each page, or do I mark them as not being present in memory and wait until I allocate the page before allocating the memory? What's involved with allocating a page? Do I simply allocate memory for the page, and set a pointer in the page table to the allocated memory? Will leaving the headers on the allocated memory segments cause issues for paging? Do the starting addressed for each page need to be aligned at a 4K address, or can each page be place wherever's convenient for the physical memory manager? I understand the overall concept of paging, but the details are lost on me at this time. What kind of functions will I need to implement for allocating and freeing pages?
https://github.com/PSanf2/POS_C9
I believe my memory manager implementation will allow me to move into paging. I would like to know where I could make improvements, or where I'm making major mistakes, before I go further. Because this is my first time writing an operating system I'm learning as I go, and wish to avoid a mistake hindering my progress later.
With my OS I'm loading the kernel at the 1M mark, and using everything after the kernel for free memory. I'm not touching anything before the kernel, and writing off the wasted megabyte as "GRUB space." I've read about having your kernel set up in the "higher half" starting at the 3G address, and then using all of the memory below that, and after the kernel, for the paging. I understand that this isn't a requirement, but how much more difficult am I making things on myself by loading my kernel in the "lower half?" I'm writing my OS for a 32-bit system, and believe that the higher half setup has something to do with making my OS compatible with other programs that wish to run at lower memory addresses. Is this correct, or am I worrying about nothing? My memory manager is currently set up to start allocating memory from the first address after the kernel, and relies on external values from the linker and GRUB to determine the proper place to start. Should I rework my OS to use a higher half kernel, and have the memory manager start allocating memory from address 0, or 1M? Once the kernel is loaded can I reclaim the "GRUB space," assuming I save the multiboot header information?
For my memory manager I'm using a doubly linked list to keep track of free memory. I'm doing this for the sake of simplicity, and aware that other data structures will provide a better algorithmic complexity. GRUB provides information telling me where my kernel ends, and how much memory I have available. Each node on the list has a "header" which I use to keep track of memory. The header on the first node is 256 bytes, and the header on each subsequent node is 64 bytes. The headers contain information telling me where the previous and next nodes in memory are, where the free memory associated with the node starts, and the size of the memory that the node contains. Allocating memory involves splitting an adequately sized node of free memory, removing the allocated node from the list, and returning a pointer to the first address of the allocated memory. The header always stays with the memory, even when it's removed from the free memory list. When I free memory, I give a function a pointer to the first address of allocated memory, back it up the proper amount to get to the header, and then put the node back on the list. From there I go over the list, and compact adjacent nodes. Basically, I have this: http://wiki.osdev.org/images/a/a4/Flat_list.png
Will I be able to use my memory manager to successfully implement paging? I understand that when I enable paging the way I use memory addresses should change. Is this an entirely logical process the programmer handles, where I translate the page index and offset into a physical address, or is the translation handled by the Memory Management Unit? I understand that to implement paging I'll need to define a page directory data structure at a 4K aligned address. I plan on implementing a new memory allocation function that will ensure the address returned is aligned properly by splitting an unallocated node at the proper place. My page directory will have 1024, 32-bit, pointers to page tables, totaling 4K in size. I'm thinking that I'll allocate 4K of memory at a properly aligned address, and that the pointer I get back will be what I give to cr3 for my page directory. The page tables will each contain 1024, 32-bit, pointers to 4K sections of memory. I'm shooting for this: http://wiki.osdev.org/images/7/77/Paging_Structure.gif When creating the page table entries, do I need to allocate the 4K memory needed by each page, or do I mark them as not being present in memory and wait until I allocate the page before allocating the memory? What's involved with allocating a page? Do I simply allocate memory for the page, and set a pointer in the page table to the allocated memory? Will leaving the headers on the allocated memory segments cause issues for paging? Do the starting addressed for each page need to be aligned at a 4K address, or can each page be place wherever's convenient for the physical memory manager? I understand the overall concept of paging, but the details are lost on me at this time. What kind of functions will I need to implement for allocating and freeing pages?