21
Softwareentwicklung / Re: Welche Compiler
« am: 26. January 2012, 10:48 »Zitat von: taljeth
Und welche Seite ist buggy?VBox

16. May 2025, 04:10
Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.
Und welche Seite ist buggy?VBox
Was Du immer mit Deinem zusammenhängen Speicher willst verstehe ich nicht. Mir fällt auf einem aktuellen PC mit einem Flat-Memory-OS absolut kein Grund ein physisch zusammenhängenden Speicher zu benötigen, nebst dessen dass das IMHO nichts mit der konzeptionellen Aufteilung des virtuellen Kernel-Space zu tun hat.Ich hänge mich da wahrscheinlich zu sehr an dem 1:1 Mapping und an der Art und Weise wie es in Linux umgesetzt ist auf. Die benutzen ja nen Buddy-Allocator und mappen auf x86 bis 768MB (glaub ich) 1:1. D.h. dann halt das du so nette Probleme wie das Bsp. was ich jetzt schon mehrmals gebracht habe, bekommst und deshalb mag ich das mit dem 1:1 Mapping nicht. Ich bin dabei aber auch davon ausgegangen, dass das dann wirklich 1:1 ist, also physisch == virtuell.
Den Teilbereich des virtuellen Kernel-Space wo der physische Speicher 1:1 gemappt wird könnte man sogar statisch festlegen so das man hier auch keine dynamischen Adressen o.ä. benötigt. Mir persönlich wäre das genug damit ich mich bei einem Flat-Memory-OS genau dafür entscheiden würde. Aber es wäre ja auch langweilig wenn jeder seine Entscheidungen so treffen würde wie ich das zu tun pflege.Damit gibst du ja den großen Vorteil von Paging auf nämlich das Umgehen der Fragmentierung des physischen Speichers.
davon ist der Durchschnitts-PC noch einige Jahre entfernt, und wenn es mal so weit ist dann taugt das heutige OS eh nicht mehr viel so dass das Versagen dann (in > 20 Jahren) durchaus verschmerzbar ist.Oh, oh, dass heißt doch wiederrum das es auch nicht schlimm ist, wenn irgendein Counter in 20 Jahren mal überläuft, ist doch verschmerzbar
Im Endeffekt ist Deine Entscheidung, Teile der Daten die eigentlich im virtuellen Kernel-Space liegen in den virtuellen Teil des jeweiligen Prozesses auszulagern, auch nur einer der möglichen Tricks um mit reinen 32 Bit-Mitteln möglichst dicht an 4 GB RAM heran zu kommen.Ich wollte den Trick nutzen, um meine Limits für alle möglichen Ressourcen so hoch wie möglich zu setzen, auch wenn es praktisch wahrscheinlich keinen Sinn geben wird. Vorallem nicht da ja die Treiber ihren eigenen Adressraum haben und das nicht auch noch im Kernel sein muss.
Oh ja, es ging doch eigentlich darum das Du eine austauschbare Speicherverwaltung für Deinen Micro-Kernel möchtest und ich der Meinung bin das die Speicherverwaltung in einem Micro-Kernel so zentral ist dass das Austauschen keinen Sinn ergibt.Da sind wir halt wieder unterschiedlicher Meinung, aber ich habe das ganze soweit abstrahiert, dass ich einfach mal um die Performance verschiedener Methoden zu testen, nur den neuen Allocator nehmen muss und 2 Funktionsaufrufe (valloc() und vfree()) anpassen muss. Ansonsten wird ja das meiste mit new (C++) gemacht und die überschriebenen Methoden müssten noch angepasst werden und schon habe ich mit verdammt wenig Aufwand nen anderen Allocator integriert. Das wäre bei deinem Konzept nicht möglich, da wäre viel mehr Aufwand für nötig.
Ich denke mit was anderem als einer Software-Abstraktion bekommt man so unterschiedliche CPU-Architekturen (was die konkrete Implementierung des Paging angeht) wie x86, x86-64, ARM und SPARC kaum unter einen Hut und da die Speicherverwaltung des Linux-Kernel deutlich mächtiger und umfangreicher als die eines typischen Micro-Kernel ist lohnt es sich IMHO durchaus da passend zu abstrahieren um die Speicherverwaltung immer gleich lassen zu können.An was denkst du da mit mächtiger? Ich denke mal die machen das nur weil es sich bei einem Monolithen halt nicht vermeiden lässt, ansonsten wird das zu aufwändig.
Wo widerspricht sich das?Naja, ich meine wozu? Unter 32bit kommst du ja auch nicht auf die Idee bei einer 2/2 Aufteilung, bei mehr als 2GB RAM ne Fehlermeldung zu schmeißen "Too much Memory". Ne Warnung könnte ich noch im höchstfall aktzeptieren, aber ne Fehlermeldung (was für mich Abbruch bedeutet)?!
An der selben Stelle im Boot-Code sollte auch noch eine Abfrage sein ob mindestens X MBytes an physischen RAM vorhanden sind damit das OS nicht schon beim Booten abstürzt.Das ist übrigens nen sehr guter Hinweis (ob mindestens so viel Speicher vorhanden ist, dass das OS läuft) und ich habe schon einige Hobby OS´e gesehen die das nicht haben sondern einfach hängen bleiben.
Hä, was meinst Du? Was hat die konkrete interne Speicherverwaltung im OS-Kernel damit zu tun wenn das OS beim Start prüft ob die Größe des benutzten physischen Adressraums für das OS im grünen Bereich liegt?Sorry, das bezog sich auf das 1:1 Mapping im Kernel.
Willst Du damit sagen das Deiner Meinung nach die Speicherverwaltung des OS-Kernels in den HAL gehört?Kann sein das wir aneinander vorbei geredet haben, aber mir ging es darum, das ich vorhabe für jede Architektur nen extra Kernel zu haben, ohne Präprozessor Zeugs. Das dort gemeinsam genutzter Code ist, sollte klar sein (z.B. VMM und PMM, da ich immer von einer MMU also Paging ausgehe), aber ich werde für jede Architektur nen neuen HAL schreiben, weil es mMn keinen Sinn macht das Interface so allgemein zu halten das es auf wirklich jeder Architektur läuft. Was dann nach außen (was der Kernel also an Syscalls anbietet) sichtbar ist, dass wird überall gleich sein, nur die Implementierung wird eine andere Sein.
Es ist doch auch relativ egal ob die Pages 4kB oder 8kB groß sind oder ob ein x-stufiges Paging-Directory in Hardware benutzt wird oder ob das per SW emuliert wird.Ich bin mir nicht mehr sicher, aber der Linux-Kernel macht sowas in der Art (Software-Emulation der Paging-Hierarchie) und da bin ich absolut dagegen. Die "paar" Zeilen Code kann man ruhig richtig auf die Hardware anpassen.
Ja. Du hast z.B. immer noch nicht angegeben wie groß der Bereich, den Dein Mini-Allocator verwaltet, eigentlich ist.Doch, hast du weiter unten sogar gequotet
Zum anderen halte ich es auch nicht für sinnvoll das statisch festzulegen, dieser Speicher ist dann für andere Zwecke verloren.Jap, der Bereich ist zur Verwaltung des Kernel-Heaps da und er ist statisch zwecks Henne-Ei-Problem bzw. Kreis-Abhängigkeiten!
Wenn ich Dich richtig verstanden habe willst Du darin die Verwaltungsdaten für den Kernel-Heap unterbringen, richtig?
Also das erscheint mir etwas zu magisch, zumindest musst Du wissen wo Du neue Pages hinmappen kannst und Du solltest auch noch zumindest einen einfachen Integerwert haben der Dir sagt wie viel noch frei ist.Also ja, ich habe ne Bitmap (für die gemappten Pages) und ne "verkettete Liste" (ist mehr nen Array mit verketteten Indizes). Soweit ich weiß führe ich nicht wirklich Buch wie viel noch frei ist. Ich habe mehr Speicher zur Verfügung als der worst-case ihn benötigt.
Nein, was ich verschlage ist den bereits vorhanden SLAB-Allocator für alles zu nutzen und nicht noch einen zusätzlichen (wenn auch primitiven) dazu zubauen.Aber ich kann diesen SlabAllocator nicht einfach gegen z.B. dlmalloc austauschen ohne dlmalloc noch modifizieren zu müssen. Bei meiner Variante geht das und das war/ist mein Ziel.
Du hast bisher gar keine konkreten Informationen über das Layout Deines virtuellen Adressraums gegebenIch bin mir eigentlich ziemlich sicher das ich das in diesem Thread schonmal gepostet hatte.
Das heist dieser Bereich gehört noch zu dem oberen 1 GB aber es gibt dort für jeden Prozess individuelle PTs (also in jedem Prozess ist dort anderer physischer Speicher eingebunden)?Jap, ist aber kein Problem da es immer ganze PTs sind.
Ja, ich bin der Meinung das man an möglichst alle Eventualitäten denken sollte und genau deswegen würde ich in den Start-Code des Kernels eine Abfrage einbauen die prüft ob der tatsächlich benutzte physische Adressraum klein genug ist um in den virtuellen Adressraum des Kernels komplett und bequem rein zu passen ansonsten gibt es eine Fehlermeldung "To much Memory".Sorry, aber das wiederspricht sich mMn ja "alle Eventualitäten denken" und "Fehlermeldung "To much Memory"". Zumal du dann wieder genau das gleiche Problem wie der Linux-Kernel hast (und genau das will ich auch nicht). Du hast 64MB frei, brauchst 128KB, aber der größte zusammenhängende Bereich ist nur 64KB groß!
widerspricht sich irgendwie. Auf der einen Seite möchtest Du möglichst viel Flexibilität und auf der anderen willst Du die Meinung vertreten das ein Micro-Kernel ruhig möglichst aus einem Guss sein soll, ich bin verwirrt.Aus meiner Sicht wiederspricht sich das nicht. Was ich bei dem MikroKernel für jede Architektur meinte ist doch, dass man alle Features so nutzt wie sie vorhanden sind (Hardware) und nicht andere drüber stülpt (Software) damit es auf allen Architekturen gleich ist.
Fürs produktive Debugging ist das natürlich nicht besonders gut.Also erstmal danke für die Mühe, aber Problem gefunden. Zumal ich das mit dem Bochs Debugging-Port ziemlich praktisch finde. Das eigentliche Problem ist ja das man auf dem Bildschirm nur begrenzt Informationen darstellen kann, aber über den Debugging-Port kann ich mir alle Ausgaben ansehen, auch "alte" (die von neueren auf dem Bildschirm verdrängt wurden).
(Aber wenn du willst, dass die Ausgabe einheitlich aussieht, musst du eigentlich nur die \t's im Inline-Assembler an der richtigen Stelle platzieren.)Ich habe nochmal nachgesehen und nach dem ich die \t´s an einer vernünftigeren Stelle platziert habe, sieht der Output auch gleich viel besser aus. Also nochmals Danke!
Mit dem C++-Code kann ich meine Frage nochmal konkretisieren: Wenn du die Ausgabe machst, werden die Variablen g_sBitmap4mb, g_sBitmap4mb4kb, g_sFree4kb, g_sFree4mb so verändert, wie es im C++-Code steht?Du hast mich damit auf etwas gebracht, auf das hätte ich selbst kommen sollen. Also nein, weder wo der Code nicht funktioniert, noch wo er "funktioniert" geht die if-Abfrage true aus.
Den einzigen Ansatz, den ich ohne weitere Rahmenbedingungen zu kennen, vorschlagen kann, wäre zu überprüfen, ob PMM_STACK_BASE tatsächlich vernünftig im Speicher platziert ist, sowie ob die statischen Variablen korrekt funktionieren. Die weiteren üblichen Kandidaten sind fehlplatzierte Stacks und unzureichende Segment Limits. Um diese Probleme von vornherein auszuschließen, würde ich empfehlen den Code als User Mode Programm testen.Ich werde mal gucken ob ich das vernünftig hinbekomme. Allerdings werde ich als erstes, einfach Bochs und den Debug-Port nutzen.
Im Code (in der Assemblerausgabe etwas seltsam eingerückt) stehen auch die dazugehörigen Labels "1:" und "2:".Das sieht so komisch aus, weil mir so wäre als wenn Labels nicht alleine stehen dürfen, sondern dahinter immer eine Instruktion folgen muss?!
Was genau heißt "funktioniert" bzw. "funktioniert nicht"?
Im Prinzip geht es darum das eine Variable auf den Wert 1024 überprüft wird und dann muss halt anderer Code ausgeführt werden. Mit dem originalen Code funktioniert das (aus irgendeinem mir nicht bekannten Grund) nicht und mit Code der nur eine Ausgabe macht (genau zw. dem ändern der Variable und dem Vergleich des neuen Wertes), funktioniert es.
#define PMM_4KB_PER_4MB 1024
static uint32 g_sBitmap4mb[PMM_BITMAP_4MB_SLOTS];
static uint32 g_sBitmap4mb4kb[PMM_BITMAP_4MB_SLOTS];
static const uint32* g_spStack4kb= (uint32*)PMM_STACK_BASE;
static uint32 g_sStack4kbPtr[PMM_MAX_4MB_PAGES];
static Spinlock g_sPmmLock;
static uint32 g_sFreeTotal4kb;
static uint32 g_sFree4kb;
static uint32 g_sFree4mb;
bool
Pmm::dealloc4kb(void* base)
{
uint32 slot;
uint32 bit;
uint32 stackNum;
uint32* stack4kb;
if(unlikely((uint32)base & 0xFFF))
return false;
//27 because 22 = 4.194.304 (size of one 4mb page) and 5 = 32 (bits in one slot)
slot= (uint32)base >> 27;
bit= ((uint32)base >> 22) & 31;
stackNum= (uint32)base >> 22;
stack4kb= (uint32*)((uint32)g_spStack4kb + (sizeof(uint32) * 1024 * stackNum));
g_sPmmLock.acquire();
stack4kb[g_sStack4kbPtr[stackNum]++]= (uint32)base;
Video::printf("stackPtr: %d\n",g_sStack4kbPtr[stackNum]);
//genau hier liegt das Problem, mit obiger Anweisung funktioniert die Abfrage, ohne sie nicht
if(unlikely(g_sStack4kbPtr[stackNum] == PMM_4KB_PER_4MB)) {
g_sBitmap4mb[slot]|= (1 << bit);
g_sBitmap4mb4kb[slot]^= (1 << bit);
g_sFree4kb-= 1023;
g_sFree4mb++;
} else {
g_sBitmap4mb4kb[slot]|= (1 << bit);
g_sFree4kb++;
}
g_sFreeTotal4kb++;
g_sPmmLock.release();
return true;
}
stack4kb[g_sStack4kbPtr[stackNum]++]= (uint32)base;
Video::printf("stackPtr: %d\n",g_sStack4kbPtr[stackNum]);
//genau hier liegt das Problem, mit obiger Anweisung funktioniert die Abfrage, ohne sie nicht
if(unlikely(g_sStack4kbPtr[stackNum] == PMM_4KB_PER_4MB)) {
movl %esi, %ebp
movl _ZL14g_sStack4kbPtr(,%esi,4), %edi
sall $12, %ebp
sall %cl, %edx
movl %ebx, -1069547520(%ebp,%edi,4)
leal 1(%edi), %ebx
movl %ebx, _ZL14g_sStack4kbPtr(,%esi,4)
cmpl $1024, %ebx
je .L25
movl %edi, %ecx
movl _ZL14g_sStack4kbPtr(,%edi,4), %edx
sall $12, %ecx
movl %eax, -1069547520(%ecx,%edx,4)
leal 1(%edx), %eax
movl %eax, _ZL14g_sStack4kbPtr(,%edi,4)
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call _ZN5Video6printfEPKcz
movl %ebp, %ecx
sall %cl, %esi
cmpl $1024, _ZL14g_sStack4kbPtr(,%edi,4)
je .L25
_ZN3Pmm10dealloc4kbEPv:
pushl %ebp
pushl %edi
pushl %esi
pushl %ebx
movl 20(%esp), %ebx
testl $4095, %ebx
jne .L24
movl %ebx, %esi
movl %ebx, %eax
shrl $22, %esi
movl $1, %edx
shrl $27, %eax
movl %esi, %ecx
andl $31, %ecx
#APP
# 39 "../../src/include/spinlock.hpp" 1
lock xaddl %edx,_ZL10g_sPmmLock
cmpl %edx,_ZL10g_sPmmLock+4
je 2f
1: pause
cmpl %edx,_ZL10g_sPmmLock+4
jne 1b
2:
# 0 "" 2
#NO_APP
movl %esi, %ebp
movl _ZL14g_sStack4kbPtr(,%esi,4), %edi
sall $12, %ebp
sall %cl, %edx
movl %ebx, -1069547520(%ebp,%edi,4)
leal 1(%edi), %ebx
movl %ebx, _ZL14g_sStack4kbPtr(,%esi,4)
cmpl $1024, %ebx
je .L25
orl %edx, _ZL15g_sBitmap4mb4kb(,%eax,4)
movl _ZL10g_sFree4kb, %eax
incl %eax
movl %eax, _ZL10g_sFree4kb
.L23:
movl _ZL15g_sFreeTotal4kb, %eax
incl %eax
movl %eax, _ZL15g_sFreeTotal4kb
movl _ZL10g_sPmmLock+4, %eax
incl %eax
movl %eax, _ZL10g_sPmmLock+4
movb $1, %al
.L21:
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
.L24:
xorl %eax, %eax
jmp .L21
.L25:
orl %edx, _ZL12g_sBitmap4mb(,%eax,4)
xorl %edx, _ZL15g_sBitmap4mb4kb(,%eax,4)
subl $1023, _ZL10g_sFree4kb
incl _ZL10g_sFree4mb
jmp .L23
_ZN3Pmm10dealloc4kbEPv:
pushl %ebp
pushl %edi
pushl %esi
pushl %ebx
subl $28, %esp
movl 48(%esp), %eax
testl $4095, %eax
jne .L24
movl %eax, %edi
movl %eax, %ebx
shrl $22, %edi
movl $1, %esi
movl %edi, %ebp
movl %esi, %edx
shrl $27, %ebx
andl $31, %ebp
#APP
# 39 "../../src/include/spinlock.hpp" 1
lock xaddl %edx,_ZL10g_sPmmLock
cmpl %edx,_ZL10g_sPmmLock+4
je 2f
1: pause
cmpl %edx,_ZL10g_sPmmLock+4
jne 1b
2:
# 0 "" 2
#NO_APP
movl %edi, %ecx
movl _ZL14g_sStack4kbPtr(,%edi,4), %edx
sall $12, %ecx
movl %eax, -1069547520(%ecx,%edx,4)
leal 1(%edx), %eax
movl %eax, _ZL14g_sStack4kbPtr(,%edi,4)
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call _ZN5Video6printfEPKcz
movl %ebp, %ecx
sall %cl, %esi
cmpl $1024, _ZL14g_sStack4kbPtr(,%edi,4)
je .L25
movl _ZL10g_sFree4kb, %eax
orl %esi, _ZL15g_sBitmap4mb4kb(,%ebx,4)
incl %eax
movl %eax, _ZL10g_sFree4kb
.L23:
movl _ZL15g_sFreeTotal4kb, %eax
incl %eax
movl %eax, _ZL15g_sFreeTotal4kb
movl _ZL10g_sPmmLock+4, %eax
incl %eax
movl %eax, _ZL10g_sPmmLock+4
movb $1, %al
.L21:
addl $28, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
.L24:
xorl %eax, %eax
jmp .L21
.L25:
orl %esi, _ZL12g_sBitmap4mb(,%ebx,4)
xorl %esi, _ZL15g_sBitmap4mb4kb(,%ebx,4)
subl $1023, _ZL10g_sFree4kb
incl _ZL10g_sFree4mb
jmp .L23
Könntest du auch machen. Ist aber mit Abstand lahmer (Compilieren ist harte CPU-Arbeit) und weniger elegant. MinGW funktioniert für das reine Compilieren von Programmen gut, und ist auch nicht als so schwer aufzusetzen, gcc, g++, gccirgentwas, gdb und die Binuits werden unterstützt und laufen ziemlich vernünftigt. msys stellt eine vernünfige Umgebung (Pfade, Shell zu Verfügung).Eben nicht, es ist bei mir um das 3.5fache schneller! Eben weil unter mingw noch der kanze POSIX-Layer KRams emuliert werden muss und das kostet richtig Zeit. Ich hätte das so auch nicht gedacht, da ich aber den neuen clang unter mingw nicht kompiliert bekommen haben und sowieso schon Linux in einer VM hatte, habe ich das mal ausprobiert und mache es jetzt nur noch so.
Wenn Dein Kernel 1 GB, also 262'144 Pages, belegt dann macht das 2 MB bis 4 MB statischen Verbrauch für Deinen Mini-Allocator. Mir persönlich wäre das zu viel.Da habe ich dann mal wieder zu wenig Infos preisgegeben. Mit statisch meinte ich eigentlich die größe des Bereichs, es werden auch dort Pages so wie sie gebraucht werden reingemappt, aber ich muss nicht Buch führen wie groß der freie Bereich ist oder ob noch genug frei ist, weil der Bereich der verwaltet wird groß genug für den worst-case ist (plus ein wenig mehr, um ein vernünftiges Alignment zu bekommen).
Wenn ich Dich richtig verstanden habe willst Du doch das oberste GB des virtuellen Adressraums dem Kernel geben, das zweitoberste GB ist dann Prozess-lokal aber trotzdem nur für den Kernel zugänglich und der Prozess bekommt dann die unteren 2 GB.Jetzt könnte ich auch schreiben, dass du mich einfach nicht verstehen willst
Bei einem 64Bit-OS trifft man ganz andere Entscheidungen. Dort wird man z.B. immer den gesamten physischen Speicher (mitsamt aller HW-Geräte) in den virtuellen Kernel-Adressraum 1:1 einblenden, einfach weil es bequem machbar ist und ne Menge grauer Haare erspart.Du bist doch immer der, der meint das man auch einen Counter der erst in über 100Jahren überläuft so programmieren sollte, das man mit dem Fall umgehen kann. Aber du willst den physischen Speicher 1:1 mappen?
Was ich mich noch frage ist warum Du überhaupt so wesentliche Teile Deines Kernels wie die Speicherverwaltung austauschbar haben willst.Ich bastle gern und will halt mal zusehen, dass ich ein vernünftiges stabiles Interface zustande bekomme. Zumal ich mir halt so die Möglichkeit offen halte, einfach den Allocator austauschen zu können. Es gibt ja immer mal wieder richtig gute neue und dann habe ich nicht viel Aufwand meinen Kernel "anzupassen".
Soweit wie beim L4, wo man sagt das (fast) jede Architektur-Variante ihren eigenen speziell angepassten Kernel bekommt, muss man ja auch nicht unbedingt gehenIst es sehr schlecht wenn ich dir jetzt sage, dass das genau meine Meinung bei einem MikroKernel ist
Wenn Du das trennen möchtest dann nur zu aber dann musst Du auch mit der Kreisabhängigkeit klar kommen, oder wo her soll sich der Kernel-VMM (unter dem Kernel-Heap-Slab-Allocator) seine Verwaltungsstrukturen holen?Naja, es klingt wahrscheinlich wieder blöd weil es von mir kommt, aber dazu habe ich noch nen Allocator geschrieben
Ich denke unsere zwei Varianten unterschieden sich vom Speicherverbrauch nicht viel (und von der Performance sicher auch nicht), es wird nur in verschiedenen Abschnitten des virtuellen Adressraum gebucht.Sie skalieren nur anders. Meine Variante hat als einzigen Engpass den Prozess und deine den allgemeinen Kernel-Allocator.
Klar könnte das in einem Kernel mit nur einem einzigen GB an virtuellem Adressraum eher knapp werden als wenn das alles Prozess-lokal läuft aber ich denke so kritisch ist das nicht und wenn doch ist es vielleicht ein guter Grund auf 64Bit umzusteigen.Auf 64bit möchte ich fürs erste verzichten, wenn ich denn irgendwann mal soweit bin, dass ne Konsole läuft und ich ein paar Treiber habe, kann ich mir darüber Gedanken machen. Bis dahin werde ich noch auf viele Probleme stoßen und diese ganzen Erfahrungen helfen dann dabei für ein 64bit OS "bessere" Entscheidungen zu treffen.
Also der Kernel-Heap muss nicht nur in der Lage sein Objekte zu liefern sondern auch ganze virtuelle Pages (ohne gleich zwangsläufig physischen Speicher dahinter zu legen, sondern nur optional). Diese Fähigkeit muss er doch eigentlich sowieso haben da er ja auch ganze Pages benutzen muss um daraus SLAB-Blöcke zu bauen (und was anderes als ganze Pages können auch nicht mit Hilfe des PMM mit echtem physischen Speicher hinterlegt werden). Dann musst Du diese interne Fähigkeit des Kernel-Heap als zusätzliches Interface verfügbar machen. Der Kernel-Heap muss doch eh intern einen Baum pflegen um den virtuellen Kernel-Speicher zu managen (so wie der Prozess-VMM den virtuellen Speicher der Prozesse managed, nur mit dem Unterschied das der Prozess-VMM für seine Baum-Objekte einfach den Kernel-Heap benutzt und der Kernel-Heap dafür sich selbst benutzen muss).Und das empfindest du nicht als Hack? Weil ich ja immer den jeweiligen Allocator um eine Funktionalität erweitern muss, die er normalerweise nicht erfüllen muss.
Warum soll das bei meinem Vorschlag nicht gehen? Solange man jeder Ebene ein sauberes Interface verpasst und die anderen Ebenen dieses Interface korrekt benutzen kann man auch jede Ebene individuell beliebig austauschen.Wenn ich die Verwaltung für die virtuellen Adressen ändern möchte, müsste ich bei deiner Idee am SlabAllocator rumspielen bzw. wenn ich den SlabAllocator gegen was anderes austauschen möchte, muss ich auch den neuen Allocator dahingehend anpassen, dass er diese Verwaltung mit beinhaltet. Das ist für mich halt weder sauber getrennt noch einfacher.
Ja, da ist die Aufgabe des Prozess-spezifischen VMMs. Den Speicher für die Baum-Elemente holt er sich aber vom Kernel-Heap (was Du hier als Allocator bezeichnet hast) und managed die nicht selber (im Gegensatz zum Heap im User-Mode oder auch im Kernel). Wenn der Prozess-spezifische VMM dann in den virtuellen Adressraum für den Prozess echte Pages legen muss holt er diese direkt beim PMM (Manager 4 in meiner Auflistung von gestern Abend) und wenn bestimmte Pages rein sollen dann kommen die eben wo anders her.So, ich unterscheide aber nicht zw. Kernel- und User-VMM. Ist eigentlich genau das gleiche (theoretisch könnte ich den Code sogar fürs ID-Management einsetzen), hat nur nen unterschiedlichen Startwert und ne unterschiedliche Größe.
Jain, und wir reden hier jetzt über den Kernel-Heap (Manager 3 in meiner Auflistung von gestern Abend). Ja, jede Page die zu einem SLAB-Block wird enthält natürlich mehrere der Elemente die der Heap nach draußen (an den restlichen Kernel) gibt (also der Rückgabewert von kmalloc()). Der Kernel-Heap hat also zwei Gründe warum er den PMM nach echten Pages fragen muss: einmal weil er ein paar Pages benötigt um einen neuen SLAB-Block für eine der Objekt-Größen zu bauen (weil für diese Objekt-Größe keine SLABs mehr frei sind) und zum anderen für den Speicher den kmalloc() liefern soll (falls in den Bereichen die bereits zum Kernel-Heap gehören nichts passendes mehr frei ist).Auch wenn das Wort Heap gerne dafür verwendet wird, mag ich es nicht. Denn die meisten assozieren damit einfach einen bereich im virtuellen Adressraum der dem Stack entgegenwächst und das trifft für meinen VMM einfach nicht zu.
Das trifft auf den Prozess-spezifischen VMM (Manager 2 in meiner Auflistung von gestern Abend) selbstverständlich zu aber nicht auf den Kernel-Heap (Manager 3 in meiner Auflistung von gestern Abend) da es Dir innerhalb des Kernels für all Deine Verwaltungsstrukturen (egal ob Bäume oder Prozess/Thread-Descriptoren oder sonstwas) egal sein kann in was für Pages die liegen.Das trifft bei mir auf den Kernel- und User-VMM zu. Ich brauche das, da ich auch Pages mappen möchte und die müssen wirklich an der Pagegröße alignt sein. Frag mich nicht warum, aber ich trenne das gerne so gut es geht (und ich weiß dass das eigentlich gar kein OO Konzept ist, durfte ich mir schon oft von meinem Prof anhören) und deswegen habe ich einmal den VMM und einmal den SlabAllocator.
Das bleibt ja auch bei meinem Vorschlag erhalten (nur mit dem Unterschied das meine 4 Ebenen jeweils etwas weniger komplex sindEben nicht, bei deinem Vorschlag (wenn ich ihn denn richtig verstanden habe) hätte der SlabAllocator auch noch die Funktion des VMMs und ich könnte keine Bereiche mehr allozieren (wo ich dann irgendwelche Pages reinmappen kann).).
Ganz ehrlich FlashBurn, manchmal habe ich so den subjektiven Eindruck das Du mich gar nicht verstehen willst.Sorry, wenn das so rüber kommt. Aber ich hatte deine Erklärung für malloc() halt so verstanden das malloc() den gesamten virtuellen Adressraum selbst verwaltet.
Das alles gilt auch für die Heap-Verwaltung im Kernel, nur das diese sich beim PMM um neue Pages bemüht. Der Speicher der vom Kernel-Heap kommt wird auch nicht in den User-Mode weitergereicht (geht ja auch nicht weil er im Kernel-Teil des virtuellen Adressraums liegt) und hat auch (üblicherweise) kein Page-Alignment, der Kernel-Heap dient dazu um z.B. die Baum-Elemente (für beide VMMs) oder die Prozess-Descriptoren unterzubringen (also alles Dinge die der Kernel nur intern benötigt).Hmm, das klingt so ähnlich wie ich es vorher hatte und damit hatte ich nur Probleme und empfinde es mehr als Hack als elegant.
Das malloc()/free() kann ja auch nicht für jede Page den Kernel fragen ob es die benutzen kann oder nicht.Da muss ich dir wiedersprechen, genau das muss es machen. Nicht malloc() bestimmt was es nutzen darf, sondern es fragt beim Kernel nach neuem Speicher. Sonst ist sowas wie ASLR gar nicht möglich. Denn woher soll malloc() wisse wie der Adressraum aussieht?
Der SLAB-Allocator muss auch nicht wissen wo noch freie virtuelle Pages vorhanden sind, wenn er ein neues Objekt liefern soll aber in seiner SLAB-Block-Liste keines mehr zu finden ist dann fordert er einfach eine/mehrere neue Seite(n) (dazu muss er natürlich in dem selber verwalteten virtuellen Adressraum ein freies Plätzchen suchen) vom PMM an und baut daraus einen neuen SLAB-Block für die gewünschte Objekt-Größe und bindet diesen neuen Block in die entsprechende Liste mit ein.Wenn der SlabAllocator nicht weiß wo nach freie virtuelle Pages/Adressen sind, woher weiß er dann wo er die physischen Pages hinmappen soll?