Autor Thema: Multitasking, Stacks und Pagetables  (Gelesen 5580 mal)

Cheebi

  • Beiträge: 91
    • Profil anzeigen
    • Cheebis Webseite
Gespeichert
« am: 06. July 2007, 00:26 »
hey Leute,

ich blicks immer noch nicht ganz... ich habe folgende fragen:

1) ich habe verstanden, warum ich für jeden prozess mindestens zwei stacks haben sollte (userstack ring3 & kernelstack ring0). aber ich weiß nicht, wie groß ich die stacks beim starten eines tasks bemessen soll, also wieviel byte malloc() allozieren soll. wenn ich den kerneltack zu groß bemesse, habe ich eine enorme speicherverschwendung (zb 10kb + pro Task). das sollte doch eigentlich nicht sein... wie löst ihr das problem?

2) beim allozieren von speicher durch malloc() ist klar, dass ich zum beispiel die stackmethode wähle, um zu wissen welche pages noch unbenutzt sind. aber ein problem ist doch, dass wenn eine anwendung beispielsweise 120kb anfordert, nicht nur 30 pages zur verfügung stehen müssen, sondern auch eine zusammenhängende folge von virtuellen adressen unbenutzt sein muss. zb virtueller speicherbereich von 0x0 bis 0x1000 ist belegt, 0x1500 bis 0x2000 belegt und bis 0x3000 ist der virtuelle speicher frei. wenn jetzt 0x1500 speicher gebraucht wird, dann ist zwar genug speicher frei, aber nicht zusammenhängend... wie kann da malloc() einen pointer auf einen zusammenhängenden speicherbereich liefern?

3) ich habe gelesen, dass man bei jedem taskswitch auch das cr3 ändert, also das pagedirectory... warum das? dann müsste ja jeder task 4mb(pagetables)+4kb(pagedirectory) haben... das ist doch auch vergeudung... oder setzt man dann das presentbit im pagedirectory nicht und spart so pagetables?

gruß

Cheebi
0100 1001 0100 1100 0100 0001 0010 0000 0011 1010 0010 1101 0010 1010
http://www.cheebi.de

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 06. July 2007, 09:52 »
Moin

ich bin zwar noch nicht ganz so fit im os coden. Aber könnte paging nicht dein problem lösen? Eine zuordnung des VirtuellenSpeichers auf den PhysikalischenSpeicher. Dadurch soll doch gerade die defragmentierung des speichers vermieden werden ( aus system weiter sicht. Prozess intern, ist das natürlich immer ein problem.).

Du richtest einen stack ein und weist im nur die erste 4 Kb kachel zu. die restlichen sind noch nicht auf PhysikalischeSpeicherbereiche zugeordnet. sollte irgendwann mehr benötigt werden, wird doch meines wissens eine Page Falt ausgelöst ( zugriff auf eine nicht zogeordneten speicherbereich)  Das gibt dir die möglichkeit gibt eine neue PhysikalischeSpeicherkachel an der entsprechenden Position einzutragen.

Paralell dazu können auch lang nicht mehr benötigte speicherzellen in eine sogenanten swap bereich ausgelagert werden, und bei bedarf ( speicherzugriff) wieder in den speicher kopiert werden.

gruss

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 06. July 2007, 11:31 »
2) beim allozieren von speicher durch malloc() ist klar, dass ich zum beispiel die stackmethode wähle, um zu wissen welche pages noch unbenutzt sind., um zu wissen welche pages noch unbenutzt sind.
malloc ist nichts, was der Kernel direkt macht, dazu müßte er bytegenau reservieren können. Der Kernel liefert normal nur komplette Pages und malloc arbeitet dann z.B. mit einer Freispeicherliste.

Zitat
aber ein problem ist doch, dass wenn eine anwendung beispielsweise 120kb anfordert, nicht nur 30 pages zur verfügung stehen müssen, sondern auch eine zusammenhängende folge von virtuellen adressen unbenutzt sein muss.
Dann war der Stack wohl einfach die falsche Wahl. ;) Und zwar gleich doppelt falsch: Du hast nämlich schon eine Datenstruktur für die verwaltung der virtuellen Seiten. Die nennt sich Page Directory bzw. Page Table und ist in der Handhabung eher einer Bitmap ähnlich, wodurch zusammenhängende Bereiche kein Problem mehr sind. Nochmal zusätzlich was aufzubauen, ist unnötig.

Zitat
ich habe gelesen, dass man bei jedem taskswitch auch das cr3 ändert, also das pagedirectory... warum das? dann müsste ja jeder task 4mb(pagetables)+4kb(pagedirectory) haben... das ist doch auch vergeudung... oder setzt man dann das presentbit im pagedirectory nicht und spart so pagetables?
Erstens wird natürlich nur der Speicher für Page Tables reserviert, die auch benutzt werden (überall sonst eben Present auf 0 setzen, wie du sagst). Und zweitens ist das nicht Vergeudung, sondern dadurch entsteht erst der Speicherschutz, daß ein Prozeß nicht im Speicher eines anderen Prozesses rumschreiben kann. Das ist der wesentliche Fortschritt des PM.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Cheebi

  • Beiträge: 91
    • Profil anzeigen
    • Cheebis Webseite
Gespeichert
« Antwort #3 am: 07. July 2007, 10:46 »

2) beim allozieren von speicher durch malloc() ist klar, dass ich zum beispiel die stackmethode wähle, um zu wissen welche pages noch unbenutzt sind.

malloc ist nichts, was der Kernel direkt macht, dazu müßte er bytegenau reservieren können. Der Kernel liefert normal nur komplette Pages und malloc arbeitet dann z.B. mit einer Freispeicherliste.
ohje... dann hab ich das falsch verstanden... ich dachte, das memorymenagement-modul des kernels kümmert sich um speicherreservierungen und stellt dafür malloc() zur verfügung. dabei dachte ich auch, dass der kernel die funktion malloc() benutzt, um beispielsweise einen prozess zu starten. angenomnmen ein prozess ist 100kb groß, dann müssen 100kb speicher für den code bereit stehen und ich brauche platz für die stacks (und evtl. noch einen datenbereich). deshalb dachte ich, der kernel würde malloc() aufrufen, um den speicher zu reservieren. wie macht der kernel das aber dann? er muss ja irgendwoher seinen speicher für den prozess beziehen...

Cheebi

0100 1001 0100 1100 0100 0001 0010 0000 0011 1010 0010 1101 0010 1010
http://www.cheebi.de

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 07. July 2007, 11:06 »
Daß du im Kernel ein malloc brauchst, kann durchaus vorkommen. Aber das ist eine Ebene tiefer als die virtuelle Speicherverwaltung, und vom Kernel per malloc reservierter Speicher ist immer nur für den Kernelspace nutzbar, nie für Prozesse (sollte jedenfalls).

Nehmen wir also mal an, ein 101 kB großes Programm soll gestartet werden (100 geht zu schön auf ;)). In diesem Fall muß der Kernel dann halt eine Anzahl Pages reservieren, in die diese 101 kB reinpassen, also insgesagt 104 kB. Drei Kilobyte bleiben dann als Verschnitt übrig, aber man kann halt nicht immer alles haben... Daß man dem Prozeß komplette Pages zuweist, ist schon allein deshalb nötig, weil der Speicherschutz des Prozessors auf Page-Ebene arbeitet. Ich kann einem Prozeß nicht erlauben, nur auf das erste Kilobyte einer Page zuzugreifen, um die restlichen drei an andere Prozesse verteilen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Cheebi

  • Beiträge: 91
    • Profil anzeigen
    • Cheebis Webseite
Gespeichert
« Antwort #5 am: 18. July 2007, 00:07 »
also ich versteh jetzt gar nix mehr  :-D

wäre jemand so nett und erklärt mir bitte, was folgende funktion (egal ob man sie nun kmalloc() oder sonst wie nennt) machen muss?

create_task(ulong entrypoint, ulong stacksize, ulong codesize, etc.)
{
  newtask.esp = kmalloc(stacksize);
  newtask.eip = entrypoint;
  copy_code_to(kmalloc(codesize));
  ...
}

das ist nur pseudocode. mir geht es einzig und allein um die hier genannte funktion kmalloc(), die ich ja wohl unbedingt brauche...
tut mir leid, dass ich so auf dem schlauch stehe, aber ich versteh einfach gar nichts mehr...

zwischenfrage:
bei einer ringtransition, wird da auch automatisch cr3 des kernels geladen? (so wie automatisch ssX und espX (X=ring) geladen werden?)

gruß

Cheebi
0100 1001 0100 1100 0100 0001 0010 0000 0011 1010 0010 1101 0010 1010
http://www.cheebi.de

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 18. July 2007, 12:18 »
Nee bei einer Ringtransition wird auch autmatisch an eine andere Adresse gesprungen. Für den Kernel z.B. 0x30000000 und im CR3 des Tasks ist dann einfach der Kernel schon gemappt aber mit einem Bit versehen, dass dort Zugriff nur mit Ring 0 gestattet ist...

Der Kernel ist also bei allen PageDirectories gemappt.

Gruss
Nooooooooooos

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #7 am: 18. July 2007, 18:09 »
Kernel:
1. Stellt Algorithmen und Datenstrukturen zum Verwalten der Speicherseiten, die alle 4kB groß sind zur Verfügung.
2. Wenn kleinere Speicherbereiche innerhalb des kernels alloziert werden müssen (zB. Prozessstrukturen, irgendwelche Zeichenketten), wird kmalloc() verwenden. Dieses kmalloc hollt die benötigen Speicherseiten natürlich aus den Funktionen die sich aus 1. ergeben.
Userspace:
Werden innerhalb des Userspace Speicherbereiche benötigt, dann wird malloc() (siehe C Standard) aufgerufen. Dies greift über einen syscall auf die Funktionen aus 1 zu (Die Speicherseiten werden dann natürlich auch in den Adressraum des Programms gemappt).
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