Autor Thema: Speicherbelegung für Task Strukturen und zugehörige Kernel Stacks?  (Gelesen 6411 mal)

ehenkes

  • Gast
Gespeichert
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?
« Letzte Änderung: 18. May 2009, 21:58 von ehenkes »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
Wieso malloc bemühen, wenn man sich auch direkt von der physischen Speicherverwaltung eine Page holen und mappen kann? Und 4k sollten für den Kernelstack eigentlich auch reichen. Aber wenn man unbedingt will, könnte man mit etwas Mühe auch einen Pagefault-Handler bauen, der sogar für den Kernel den Stack dynamisch vergrößert, wenn er benötigt wird.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

ehenkes

  • Gast
Gespeichert
Habe ich das richtig verstanden, dass man für jede Task einen Kernelstack anlegt? Da hat mich letzt jemand verunsichert, meinte ein Kernel-Stack für alle Tasks würde reichen.  :?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
Man kann das sicher auch mit weniger machen (aber weniger als ein Stack pro CPU wird schwierig). Allerdings solltest du dir bewußt sein, wie dein Multitasking im Moment funktioniert: Der Zustand eines Tasks liegt oben auf seinem Kernelstack. Wenn man diesen Stack auch noch für andere Tasks mitverwendet, stimmt das natürlich nicht mehr. In diesem Fall müßte man den Zustand irgendwo anders hinspeichern.

Sind alles nur Designfragen, man kann es theoretisch so oder so machen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
Der Vorteil bei 4kB Kernelstacks (wenn man nicht mehrere auf eine Page zwängt) ist, dass wenn man eine page frei lässt, kann man einen Overflow erkennen. Das geht halt nicht wenn man zwei Stacks auf eine Page zwängt.
Und Kernelstacks vergrößern? Ich weiß nicht... das macht nichtmal Linux als monolithischer Kernel... bei denen ist aber deshalb auch Rekursion im Kernel nicht gern gesehen.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

 

Einloggen