Hello,
When creating tasks it is obviously necessary to save all the physical frames that the tasks uses so they can be freed when the task is killed and used for another task. So when a task uses 8mb it uses 2048 frames which multiplied by the sizeof a void* becomes 8kb which is obviously way to much when there are for example 200 tasks. So what is a better way to save these addresses?
-thomtl
[SOLVED] How to save physical frames used by tasks
[SOLVED] How to save physical frames used by tasks
Last edited by thomtl on Wed Sep 19, 2018 7:56 am, edited 1 time in total.
Re: How to save physical frames used by tasks
You already store those addresses in Page Tables.
If something looks overcomplicated, most likely it is.
Re: How to save physical frames used by tasks
Storing 1kb of accounting information per megabyte (or 0.1% of memory) is "obviously way too much"!? I doubt you'll find a "fully featured" OS that's anything like that efficient!thomtl wrote: So when a task uses 8mb it uses 2048 frames which multiplied by the sizeof a void* becomes 8kb which is obviously way to much when there are for example 200 tasks.
For reference; Linux (not an example of the best designed kernel, but it's popular and probably fairly "typical" in this regard) holds a "struct page" per physical page that contains informtion about which process is using that page, what for, etc. That struct is 32-64 bytes depending on the architecture, or at least 8kb per megabyte (0.8% of memory).
Re: [SOLVED] How to save physical frames used by tasks
Sounds like you are talking about a memory manager. I just switched over from a descriptor-based approach to a bitmap-based approach.
In the descriptor based approach, a process could request any size memory in blocks of 4k, and the memory manager would create a 24 byte descriptor to track that (a bit like an f-node on a file system). However, for a tight, efficient memory manager this turned out to be way too costly in terms of code maintenance (complexity, in assembler, is very costly).
Instead I switched to larger blocks (16k) that are tracked in 2 bitmaps. The first bitmap tracks usage and the second tracks which block is the first in a sequence of contiguous blocks (which makes it easier to deallocate and ensure blocks don't get deallocated out of sequence).
The upshot is that I need 2 BITS of ram to be able to allocate and deallocate 16k blocks. If my calculator is not broken, 8 bytes of bitmap manages 2 MiB of RAM. My OS is being designed to run in about half a Gig, so that's a good trade-off for me.
Of course, I still have a problem to solve - what happens when a process dies without deallocating its memory? I may still need a descriptor for that, but I will worry about that down the road. For now, I can move forward to a TCP stack that can get and release the needed buffers. I'll cross that other bridge when the chickens have hatched. Or something.
In the descriptor based approach, a process could request any size memory in blocks of 4k, and the memory manager would create a 24 byte descriptor to track that (a bit like an f-node on a file system). However, for a tight, efficient memory manager this turned out to be way too costly in terms of code maintenance (complexity, in assembler, is very costly).
Instead I switched to larger blocks (16k) that are tracked in 2 bitmaps. The first bitmap tracks usage and the second tracks which block is the first in a sequence of contiguous blocks (which makes it easier to deallocate and ensure blocks don't get deallocated out of sequence).
The upshot is that I need 2 BITS of ram to be able to allocate and deallocate 16k blocks. If my calculator is not broken, 8 bytes of bitmap manages 2 MiB of RAM. My OS is being designed to run in about half a Gig, so that's a good trade-off for me.
Of course, I still have a problem to solve - what happens when a process dies without deallocating its memory? I may still need a descriptor for that, but I will worry about that down the road. For now, I can move forward to a TCP stack that can get and release the needed buffers. I'll cross that other bridge when the chickens have hatched. Or something.
Code or code not. There is no try.