Eine Frage im Rahmen von Multitasking: kmalloc(...) belegt bei vorhandenem Heap z.B. auch für Kernelstacks beim Multitasking Platz auf dem Heap, also Stack auf dem Heap. Irgendwie verwirrend, obwohl es sogar funktioniert. Wie macht das tyndur, wenn es kernel stacks anlegen muss?
Ich habe mir nun noch ein kmalloc_stack(...) geschrieben, dass auch bei vorhandenem Heap im Paging bereits gemappte Seiten (ca. 0x100000) mittels Vorschieben von placement_address für task_t und zugehörigen task_t->kernel stack reserviert.
Beispiel mit
task_t* new_task = (task_t*)k_malloc_stack(sizeof(task_t),0,0);
new_task->kernel_stack = k_malloc_stack(KERNEL_STACK_SIZE,1,0)+KERNEL_STACK_SIZE;
id: 1 esp: 00000000h eip: 00000000h PD: 00000000h k_stack: 0020B800h next: 0020C000h
id: 2 esp: 0020D7C0h eip: 00008299h PD: 40101000h k_stack: 0020D800h next: 0020E000h
id: 3 esp: 0020F7C0h eip: 00008299h PD: 40104000h k_stack: 0020F800h next: 00210000h
id: 4 esp: 002117B4h eip: 00008299h PD: 40107000h k_stack: 00211800h next: 00000000h
Gleiches Beispiel mit üblichem kmalloc auf einem Heap:
task_t* new_task = (task_t*)k_malloc(sizeof(task_t),0,0);
new_task->kernel_stack = k_malloc(KERNEL_STACK_SIZE,1,0)+KERNEL_STACK_SIZE;
id: 1 esp: 00000000h eip: 00000000h PD: 00000000h k_stack: 40101800h next: 40101814h
id: 2 esp: 401057C0h eip: 00008299h PD: 40102000h k_stack: 40105800h next: 40101844h
id: 3 esp: 401097C0h eip: 00008299h PD: 40106000h k_stack: 40109800h next: 40101874h
id: 4 esp: 4010D7B4h eip: 00008299h PD: 4010A000h k_stack: 4010D800h next: 00000000h
Wie macht ihr das?
Man könnte eine Task-Struktur natürlich auch auf dem Heap anlegen. Ein Stack gehört meines Erachtens aber nicht auf den Heap. Welche Stacksize nimmt man für Kernel Stacks, damit es hier keine Platzprobleme gibt? Reichen 2048 Byte?
Wie ihr seht wurde die Page Directory (PD) auf dem Heap angelegt.
Sollte man die PDs, Tasks auf dem Heap und die zugehörigen Kernel Stacks in einem besonderen Bereich via placement address geschützt anlegen?
Was wäre der richtige Name für dieses k_malloc_stack(...)?
ULONG k_malloc_stack(ULONG size, UCHAR align, ULONG* phys)
{
if( !(placement_address == (placement_address & 0xFFFFF000) ) )
{
placement_address &= 0xFFFFF000;
placement_address += PAGESIZE;
}
if( phys )
{
*phys = placement_address;
}
ULONG temp = placement_address;
placement_address += size; // new placement_address is increased
return temp; // old placement_address is returned
}
Nachteilig ist, dass man im Paging vorab hierfür ausreichend Frames allokieren muss.
// Allocate ... extra so the kernel heap, tasks and kernel stacks can be initialised properly.
// map (phys addr <---> virt addr) from 0x0 to the end of used memory
i=0;
while( i < placement_address + 0x100000 ) // important to add more!
{
alloc_frame( get_page(i, 1, kernel_directory), 0, 0);
i += PAGESIZE;
}
Auf der anderen Seite ist das mit der Placement-Adresse nicht elegant, weil man dahinter nichts mehr frei gibt. Wenn ein Task beendet wird, kann man den zugehörigen Stack ja wieder frei geben, auf dem Heap kein Problem.
Es sind ziemlich viele Varianten denkbar.
Wie sieht eure Lösung aus, und warum habt ihr euch gerade dafür entschieden?