Hi,
makerimages wrote:Right now I have the identity mapped 1MB set up and paging enabled. What I'm struggling to understand how to implement now, is the logic that comes after a malloc call. More precisely, I've managed to come up with the following questions.
- Where does malloc get the virtual address to return?
- Am I correct in my understanding, that the logic that should happen once the code calls malloc, is something like this?
- Somehow find the next free virtual address in the address space (how?) What does this address represent? index of page table in dir + index of entry in table?
- See if that address is already mapped (in the page directory of this process, go over page tables and do What?)
- If not, add to the page table an entry. Find the next free physical block (but don't access it!), build the entry, and insert it. Access the virtual address to do anything else needed (like get next from a linked list
- Return virtual address
Note: for C, "malloc()" typically uses "brk()" or "mmap()" (or both) to get more memory. This doesn't really change much (it just means that your next question would be where "brk()" or "mmap()" get addresses from). Also note that "how C's standard library works" may be (and I'd be tempted to say "should be") entirely irrelevant - e.g. processes in user-space can be written in any of 100+ languages (where C is only one of many) and you really want something that all possible languages (including those that don't exist yet) can use regardless of how the language and its run-time are designed (and not something that is only designed for one language that is potentially crippled for other languages).
In general, for "what decides which areas of the virtual address space are used for what", people are divided:
- Some people put it in the virtual memory manager (in the kernel), where a thread would ask kernel to (e.g.) allocate some pages and the kernel finds a free place to put the pages and then allocates them.
- Some people put it in user-space, where (e.g.) a thread finds a free place to allocate some pages itself and then ask kernel to allocate free pages at a specific virtual address, and kernel only allocates them (at the address it was told).
The former is easier, but the latter is more flexible. For C it makes no difference (any differences are buried by the C library, so normal C code doesn't need to know).
I do the latter. More specifically, my kernel's virtual memory manager has a function that user-space can use to change the "virtual type" of any area of user-space it likes - sort of like "
int change_virtual_type_for_area(void *start_page, int number_of_pages, int new_type);". User-space does whatever it wants with its virtual address space in any way it wants to; which might be "brk()" (which mostly only needs "data_area_top" variable to manage) or something more advanced/complex, or something completely different, or nothing (e.g. pre-determined at compile-time), or 20 different things (in 20 different zones). Note that my kernel's "change_virtual_type_for_area()" is quite dangerous because it does what it's told (and overwrites the old virtual type/s regardless of what they were before). For example, with a single "change_virtual_type_for_area()" you could change the type of every page in user-space to the "not present" virtual type (and then crash because your own code doesn't exist after that).
Cheers,
Brendan