Need help with morecore()
Need help with morecore()
I have intialized paging. I have written a page frame allocator using stack approach. Now the next step is to write malloc and free, for kernel heap management. I am keeping my kernel heap at 0XD0000000. My understanding is that malloc calls morecore to allocate more memory to the heap. Also , from what I know , whether its user level malloc or kernel space malloc, both call morecore , and the only argument passed to morecore is the number of bytes requested. So that implies the appropriate page directory has to be loaded prior to the call to morecore(), but even then i suppose for every address space, the region 0xD0000000 will correspond to the kernel heap. So how is morecore supposed to know whether the current request is for the kernel heap or user process heap, because morecore is the one that manipulates the pagedirectory entry to reflect addition to the heap right???.Is this anywhere close to being correct or have I gotten thing completely wrong??
I will not say that you're understanding it wrong, as there are so many different ways you can do things in os development, but it is certainly different from the way I approached the problem.
First, I define two areas of my virtual address space. One is the kernel heap and one is the user heap. They have an initial size of 0, but can grow up to any size. The only information about them I store is a base address and a length (or you could use an end address). All that a call to morecore/sbrk does is increase the size of the heap by changing the end/length variable (which are global variables in kernel space). The kernel morecore/sbrk changes the kernel end/length, whilst a user mode one calls a syscall, the kernel-side handler for which changes the user end/length. Calling morecore does not affect the page tables/directories in any way.
So at this stage, malloc (which calls morecore/sbrk) has returned a void* address which refers to an as yet unmapped area of memory. When the kernel/program tries to access this memory, a page fault will be triggered. This is expected. The page fault handler then compares the faulting address with the kernel and user heap variables to see if the faulting address lies within a heap. If so, it asks the physical memory allocator for a page, and then maps it to the correct address. You set the permissions so that the kernel heap is not accessible by a user process. You also don't allow a kernel space mapping to occur, if the fault occurred in a user process (you can check the error code pushed for the page fault exception for this).
This lazy-allocation scheme can then be extended to include other sorts of memory areas other than heaps, for example you can have your stack grow downwards if it overruns a page. I personally maintain a list of memory sections per process, including things such as the heap, stack, any thread local storage areas, as well as a link to the global kernel sections. You can further add to this sections for parts of executables (e.g. .text, .data, .bss) with an additional flag to say "if a page fault occurs within this section, do not ask the physical memory allocator for an empty page, but map this area of the executable image instead" so you can use the same page fault handler as a lazy-loader for executables. But I'd get the malloc working first.
Regards,
John.
First, I define two areas of my virtual address space. One is the kernel heap and one is the user heap. They have an initial size of 0, but can grow up to any size. The only information about them I store is a base address and a length (or you could use an end address). All that a call to morecore/sbrk does is increase the size of the heap by changing the end/length variable (which are global variables in kernel space). The kernel morecore/sbrk changes the kernel end/length, whilst a user mode one calls a syscall, the kernel-side handler for which changes the user end/length. Calling morecore does not affect the page tables/directories in any way.
So at this stage, malloc (which calls morecore/sbrk) has returned a void* address which refers to an as yet unmapped area of memory. When the kernel/program tries to access this memory, a page fault will be triggered. This is expected. The page fault handler then compares the faulting address with the kernel and user heap variables to see if the faulting address lies within a heap. If so, it asks the physical memory allocator for a page, and then maps it to the correct address. You set the permissions so that the kernel heap is not accessible by a user process. You also don't allow a kernel space mapping to occur, if the fault occurred in a user process (you can check the error code pushed for the page fault exception for this).
This lazy-allocation scheme can then be extended to include other sorts of memory areas other than heaps, for example you can have your stack grow downwards if it overruns a page. I personally maintain a list of memory sections per process, including things such as the heap, stack, any thread local storage areas, as well as a link to the global kernel sections. You can further add to this sections for parts of executables (e.g. .text, .data, .bss) with an additional flag to say "if a page fault occurs within this section, do not ask the physical memory allocator for an empty page, but map this area of the executable image instead" so you can use the same page fault handler as a lazy-loader for executables. But I'd get the malloc working first.
Regards,
John.
I am not able to understand how the lazy allocation will work correctly . I mean if the morecore function simply increases the size of the heap by the requested amount , and the the page fault handler later finds that actually there is no more physical memory remaining,ie all available pages are in use, then there will be no choice but to terminate the process, when actually the morecore supposedly returned available memory. and moreover it will not be a graceful failure for that process