I am reading the JamesM's kernel development tutorial and in the "chapter" that explain how to setup the paging memory management mechanism, he shows the kmalloc() function, that should allocate some memory.
This is the function :
u32int kmalloc(u32int sz) {
u32int tmp = placement_address;
placement_address = sz;
return tmp;
}
I am a little bit confused about. How does this function allocate memory?
It returns the address where the allocated chunck should be, but I really don't understand how the actual allocation works.
CodePudding user response:
This is the simplest memory allocation mechanism. placement_address
is initialized when booting to point to a start of some big, contiguous memory block. This kmalloc
assigns sequential chunks of it as requested.
I think the problem comes from understanding of the world "allocate". Here it's used in the very basic meaning of the term: it tells the caller where requested chunk is and takes note that it's no longer available, so it won't be returned again. Nothing more. There is no deallocation, no OOM, no boundaries and all interaction with physical memory (if it happened) was done once at startup.
Think of a ticket seller with a roll of tear-off tickets: you say "sz tickets please", so they start at the current end of the roll (placement_address
), they advance their "end" sz
places (placement_address = sz
) and handle you the previous "end" (return tmp
). The tearing away of paper tickets has no equivalent here. You're wondering on "how was the roll printed", but "allocation" doesn't mean printing, it only means handling it away in pieces.
CodePudding user response:
It looks to me like u32int
is a type that holds a number which in turn references a memory address. placement_address
is also a u32int
, which I would guess is the address of the start of a large memory block that has been allocated already. When you request an allocation of size sz
, you are given the current placement_address
, which is a pointer to some pre-allocated memory. We then advance the pointer by the size requested, so next time the function is called we return placement_address
again, but it has been advanced so it uses different memory.
Note that this doesn't create segmentation faults - if you allocate 2 bytes and then write on to the 3rd, it is technically allocated but just to another part of the program. I've written out a simplification in code below
u32int placement_address = malloc(40000); //allocate 40kb for kmalloc to hand out
u32int kmalloc(u32int sz) {
u32int tmp = placement_address; //temporarily store the return pointer
placement_address = sz; //advance pointer by memory used for next allocation
return tmp; //return pointer somewhere in malloc'ed area
}
u32int item = kmalloc(5); //returns placement_address
u32int item2 = kmalloc(3); //returns placement_address 5 (see above line)
u32int item3 = kmalloc(40); //returns placement_address 5 3 (see above 2 lines)
char valid = (*(item3 5)) //get the data in memory at placement_address 48. With
//malloc, this should make a segmentation fault, but the
//memory is already allocated when using kmalloc. This
//can create some really difficult to find bugs if done
//accidentally!