Eigenes OS?
-
+fricky schrieb:
blitzmaster schrieb:
also ich würde euch empfehlen, das ganze über interrupts zu machen. da gibts dann später bei multitasking keine probleme, da bei einem interrupt autamtisch das i-flag in den eflags gelöscht wird, sodass der kernel nicht unterbrochen werden wird...
interrupts global zu sperren (macht man das mit dem i-flag?) ist, wenn nicht unbedingt erforderlich, eigentlich keine gute idee, weil dann interrupt-anforderungen verloren gehen können, wenn die sperre zu häufig eingesetzt wird oder lange dauert. und ich weiss nicht, ob die pc-architektur 'nested' interrupts und interrupt-prioritäten kennt (ich glaub' die hardware unterstützt es nicht, aber es geht mit software-tricks).
Jo, das IF ignoriert praktisch die IRQ-Line der CPU (nicht aber NMIs, exceptions, usw.).
AFAIR: Selbst der PIC (programmable Interrupt Controller) in den ersten PCs kannte schon eine Prioritaetsbehandlung von IRQs. Das Ding wurde dann zunaechst in typischer x86-manier erweitert, indem man quasi den gleichen Controller nochmal hinten dran geklatscht hat (toll: jetzt mit 16 IRQs!!) und inzwischen gibt es den in die CPU integrierten APIC.
IAR geht also nichts verloren, wenn das IF geloescht wird ... es sei denn, das bleibt ueber Sekunden so (daher auch meine Ermahnung, schnelle IRQ-handler zu schreiben).
Dennoch hast du recht: IRQs sollte man nur ausschalten, wenn unbedingt noetig, was bei x86ern mit ihren ganzen atomaren spezial-Befehlen im Prinzip relativ selten vorkommen duerfte.+fricky schrieb:
blitzmaster schrieb:
Aber nachdem das ja ein Sprung in den Kernel ist, könnte es sein, dass dann zwei Tasks gleichzeitig springen und im Kernel dann Datenstrukturen zerstört werden, weil das nicht synchron geschieht.
in einem multitasking-os sollten systemfunktionen sowieso immer reentrant-fähig sein. dass mehrere task gleichzeitig im kernel rumschwirren, oder gar die selbe systemfunktion nutzen, ist keine seltenheit.
Richtig. Da kann man entweder alle moeglichen Teile des Kerns einzeln in kritische Sektionen packen, oder man tuetet den ganzen Kern einfach in eben eine solche. Zu Demonstrationszwecken im Rahmen eines Tutorials waere das IMHO uebersichtlicher. Dabei kann man dann auch problemlos IRQs zulassen.
Int loescht uebrigens nicht das IF. AFAIR sysenter genau so wenig.
Die Entscheidung gegen sysenter und fuer int befuerworte ich uebrigens (wie ich schon sagte) : Kein neuer Spezial-Befehl, Gebastel mit AMD vs. Intel, einfache Handhabung, abwaertskompatibel. KISS halt.BTW ist die Benutzung eines eigenen Stacks fuer Kern-Aufrufe (auch IRQ- und Exception-Handler) wie gesagt dringend zu empfehlen. Praktisch fast wie ein TASK-Switch.
-
Nobuo T schrieb:
Int loescht uebrigens nicht das IF. AFAIR sysenter genau so wenig.
So weit ich weiß, wird das IF bei einem Sprung zu einem Interrupt Gate gelöscht.
-
Erhard Henkes schrieb:
in einem multitasking-os sollten systemfunktionen sowieso immer reentrant-fähig sein. dass mehrere task gleichzeitig im kernel rumschwirren, oder gar die selbe systemfunktion nutzen, ist keine seltenheit.
Klingt wirklich herausfordernd, erinnert mich an multithreading.
isses auch. multithreading und -tasking bedeutet, je nach kontext, mal was anderes, mal das selbe. windows-user verstehen unter multitasking, dass gleichzeitig mehrere prozesse möglich sind, von denen jeder mehrere threads (==parallel ausführbare einheiten) haben kann. in der RTOS-terminologie wird das, was unter win 'thread' heisst, oft 'task' oder 'prozess' genannt.
Nobuo T schrieb:
BTW ist die Benutzung eines eigenen Stacks fuer Kern-Aufrufe (auch IRQ- und Exception-Handler) wie gesagt dringend zu empfehlen. Praktisch fast wie ein TASK-Switch.
dann haste aber ein ziemlich schwergewichtiges interface zwischen kernel und userland, das syscalls relativ unperformant macht. eigentlich braucht man doch nur einen privilegwechsel beim sprung in den kernel und bei der rückkehr. natürlich musste noch checken, ob die parameter gültig sind, genug platz auf dem stack ist, pointer sinnvollen inhalt haben und ähnliche kleinigkeiten. einen kompletten, task-switch ähnlichen mechanismus, halte ich für übertrieben. aber vielleicht geht's mit den x86 software-int befehlen nur so (weshalb später 'sysenter' eingeführt wurde).
-
Die system calls laufen. Man kann also nun z.B. die Funktion puts(...) als syscall_puts(...) aufrufen. Ich benötige mal eure Hilfe, da ich momentan etwas nicht verstehe und nicht sicher bin, ob das genau so richtig ist oder ob im OS etwas nicht stimmt (was mir wahrscheinlicher erscheint).
Ich habe hier zwei Varianten:
http://www.henkessoft.de/OS_Dev/Downloads/31&32.zip
31) nach dem switch_to_user_mode() hat der user privileg 0
32) nach dem switch_to_user_mode() hat der user privileg 3Im ersten Fall:
switch to user mode
After set_kernel_stack. tss_entry.esp0: 0000083Ch
Right before user modeIRQ 127<<<Hello, user world!
behind switch to user mode with ring 0 supervisor privilege!
SS: 00000010h, ESP: 0018FFE0h, EBP: 0018FFF0h, CS: 00000018h, DS: 00000020hDas "Hello, user world!" wird mittels syscall_puts(...) ausgegeben. Daher weiß ich, dass die system calls nun funktionieren. Baut man auf diese Weise ein API auf? (habe das bisher noch nie gemacht )
switch_to_user_mode(); syscall_puts("Hello, user world!\n");
Im zweiten Fall:
switch to user mode
After set_kernel_stack. tss_entry.esp0: 0000083Ch
Right before user mode
Page FaultException. System Halted! <<<
Ich bin etwas irritiert darüber, dass im echten User Mode der Syscall (ring 3 ruft ring 0) vor dem Page Fault (wegen unerlaubtem Zugriff auf Kernel code) nicht durchgegangen ist. Vielleicht liegt es daran, dass auf dem Weg zur Ausführung des Syscalls (... -> IRQ127 -> syscall_handler -> ...) bereits ein "Page Fault" erfolgte.
Sorry, dass der Code im IRQ-Bereich momentan etwas "gestöpselt" ist. Das muss ich noch aufräumen, wollte jetzt nur erst mal das Tasking und die Syscalls zum Laufen bekommen, denn die Schnittstelle zwischen Kernel und Anwendungen im User Mode sind ja genau das Interessante.
Wenn ich das so nebeneinander sehe, wundere ich mich gerade über die Leerzeile zwischen Right before user mode und >>>IRQ 127<<<Hello, user world!.
Die nächste Aufgabe ist jetzt, den vorhandenen Code vernünftig zu überarbeiten, damit er eine wirklich brauchbare Basis für ein OS ergibt, möchte nicht völlig chaotisch weiter hetzen, weil dann die Didaktik und vor allem das Tutorial auf der Strecke bleibt. Schlechten Code erklärt und zeigt man nicht gerne, sondern ist froh, wenn er läuft. Damit Experimentieren ist zumeist auch nicht gerade lustig. Vielleicht, wenn man die Module noch ordentlich sortiert und hier und da entkoppelt, kann das noch etwas Sinnvolles werden?
Vielleicht kann sich ein Assembler-Spezialist die IRQ/ISR/exception-Story mal anschauen (z.Z. eine wilde Mischung aus ASM und C). Da blicke ich kaum noch selbst durch. Den int127 (128 ging nicht wegen Überlauf, muss ja auch nicht sein, wäre nur wegen Linux 0x80) habe ich schon an den fault_handler, der eigentlich nur für exceptions gedacht war, "provisorisch angeschraubt", ging irgendwie nicht anders. Aber so ist wahrscheinlich auch Windows und Linux entstanden.
Inzwischen habe ich gehörig Respekt vor der OS-Entwicklung.
... und das Schwierigste liegt ja eher noch vor mir.
-
..
Gut finde ich bisher,
- dass nicht der GRUB Loader verwendet wird
- den sauberen Übergang von Assembler zum C-Kernel (thanks to Nobuo T)
- die Bitset-Verwaltung beim Paging (effizient)
- das VFS analog Linux (leider noch nicht richtig in Aktion)Schlecht finde ich
- das Interrupt-Gerödel (richtig zusammen geschustert, da verwende ich sogar noch den alten Aufbau, weil James das auch nicht wirklich auf die Reihe bekam, ist jedoch im Wesentlichen Fleißarbeit, das zu ordnen)
- die AT&T Syntax innerhalb C (ziemlich unverständlich, das gehört wirklich alles als Intel Syntax ausgelagert, da hat abc.w Recht)Unsicher bin ich mir bei
- der Heap-Erzeugung/-Verwaltung (schwieriges aber langweiliges Thema, Hauptsache läuft erstmal)
- der Tasking-SteuerungDas wird aber alles noch richtig gut, da bin ich ganz sicher.
Ich musste für mich schnell Zusammenhänge praktisch durchspielen, daher der Rückgriff auf Vorhandenes, um zu sehen, was wirklich voneinander abhängt. Übrigens geht es anderen auch so. Selbst, wenn ich den Sourcecode alleine erfinde, bringt das niemand weiter. Für andere ist der Code immer "fremd". Was zählt, sind gute Erklärungen. Da sieht es in James Molloy's Tutorial allerdings düster aus.
Was mir bisher noch weitgehend fehlt, ist die Darstellung der Arbeitsweise des OS. Ich möchte kein "unsichtbares" OS, sondern einen "offenen Wecker". Da habe ich bisher überhaupt noch keinen Ansatz gefunden, das ist bei vielen "Educational OS" lauter in sich geschlossenes unverständliches "Gefrickel".
..
-
..
-
So sieht momentan ein typischer Bildschirmausdruck zur Überprüfung aus:
..Bezüglich Visualisierung des Pagings habe ich mal Folgendes probiert:
Um das Bitset mit seinen Nullen und Einsen und den Bezug zu den Speicheradressen darzustellen, habe ich die unten stehende Funktion entworfen. Sie bleibt 'sec' Sekunden stehen, wenn eine oder mehrere Einsen (allokierte Pages) auftauchen, bei Nullen flitzt sie durch. Damit kann man recht praktisch den Speicher scannen und sich in Bochs mit copy von der jeweils interessanten Region screenshots machen:void analyze_frames_bitset(ULONG sec) { ULONG index, offset, counter1=0, counter2=0; for(index=0; index<(NFRAMES/32); ++index) { settextcolor(15,0); printformat("\n%x ",index*32*0x1000); ++counter1; for(offset=0; offset<32; ++offset) { if( !(frames[index] & 1<<offset) ) { settextcolor(4,0); putch('0'); } else { settextcolor(2,0); putch('1'); ++counter2; } } if(counter1==24) { counter1=0; if(counter2) sleepSeconds(sec); counter2=0; } } }
Diese Funktion geht sämtliche Pages durch und stellt jeweils 32 in einer Zeile je nach Allokation als Null oder Eins dar. Vorne steht die erste Hex-Speicheradresse der ersten Page (also jeweils 4KB * 32 = 128KB in einer Reihe).
Bsp.: Erstes Ende der kompakten Allokierung oberhalb 18 MB (1200000h) :
011C0000h 11111111111111111111111111111111 011E0000h 11111111111111111111111111111111 01200000h 11111111111111111110000000000000 01220000h 00000000000000000000000000000000
Screenshot: http://www.henkessoft.de/OS_Dev/Bilder/Paging_Scan.PNG
Bsp.: #define KHEAP_START 0x40000000 // 1GB
#define KHEAP_INITIAL_SIZE 0x100000
#define KHEAP_MAX 0x4FFFF000
Dort befindet sich auch die RAM Disk:3FFC0000h 00000000000000000000000000000000 3FFE0000h 00000000000000000000000000000000 40000000h 10100110000011001000100010000000 40020000h 10100000000000101000100010000000 40040000h 10100000000010101000100010000000 40060000h 10100000000001101000100010000000 40080000h 10100000000011101000100010000000 400A0000h 10100000000000011000100010000000 400C0000h 10100000000010011000100010000000 400E0000h 10100000000001011000100010000000 40100000h 10100000000011011000100010000000 40120000h 10100000000000111000100010000000 40140000h 10100000000010111000100010000000 40160000h 10100000000001111000100010000000 40180000h 10100000000011111000100010000000 401A0000h 10100000000000000100100010000000 401C0000h 10100000000010000100100010000000 401E0000h 10100000000001000100100010000000
usw.
Zum Verständnis die Bitset-Funktionen aus paging.c:
..Nun "sieht" man endlich, was man macht.
Solche Dinge sind mir wie bereits ausgeführt wichtig.EDIT: Ebenfalls hilfreich ist eine Analyse der physikalischen Adressen der Startadressen der Pages:
ULONG show_physical_address(ULONG virtual_address) { page_t* page = get_page(virtual_address, 0, kernel_directory); return( (page->frame_addr)*PAGESIZE + (virtual_address&0xFFF) ); } void analyze_physical_addresses() { int i,j,k, k_old; for(i=0;i<(PHYSICAL_MEMORY/0x18000+1);++i){ for(j=i*0x18000; j<i*0x18000+0x18000; j+=0x1000){ if(show_physical_address(j)==0){ settextcolor(4,0); k_old=k; k=1; } else{ if(show_physical_address(j)-j){ settextcolor(3,0); k_old=k; k=2; } else{ settextcolor(2,0); k_old=k; k=3; } } if(k!=k_old) printformat("%x %x\n", j, show_physical_address(j)); } } }
00000000h 00000000h
00001000h 00001000h
01113000h 00000000h
01400000h 12389000h
40100000h 00000000h
40400000h 12389000h12389... ist eine "Magic Number" (#define HEAP_MAGIC 0x123890AB in kheap.h)
-
Um den Page Fault näher zu beschreiben, wurde jetzt folgende Auswertung eingebaut:
if (r->int_no == 14) //Page Fault { ULONG faulting_address; asm volatile("mov %%cr2, %0" : "=r" (faulting_address)); // faulting address => CR2 register // The error code gives us details of what happened. int present = !(r->err_code & 0x1); // Page not present int rw = r->err_code & 0x2; // Write operation? int us = r->err_code & 0x4; // Processor was in user-mode? int reserved = r->err_code & 0x8; // Overwritten CPU-reserved bits of page entry? int id = r->err_code & 0x10; // Caused by an instruction fetch? // Output an error message. printformat("Page Fault ("); if (present) printformat("page not present"); if (rw) printformat("read-only - write operation"); if (us) printformat("user-mode"); if (reserved) printformat("overwritten CPU-reserved bits of page entry"); if (id) printformat("caused by an instruction fetch"); printformat(") at %x - EIP: %x\n", faulting_address, r->eip); }
Test mit Page Fault: http://www.henkessoft.de/OS_Dev/Downloads/34.zip
Der Page Fault wurde provoziert durch Streichen des Extra-Speichers oberhalb der placement_address:
// Allocate a little bit extra so the kernel heap can be initialised properly. // map (phys addr <---> virt addr) from 0x0 to the end of used memory ULONG counter=0; i=0; while( i < placement_address /*+ 0x100000*/ ) //important to add more! { alloc_frame( get_page(i, 1, kernel_directory), 0, 0); i += PAGESIZE; ++counter; }
Dadurch kann man heraus finden, wieviel Speicher allokiert werden muss, um den Kernel Heap zu initialisieren. Endlich mal eine Aufgabe für die Leser.
Antwort: Bei 0x0 0der 0x1000 erfolgt ein Page Fault. Die Info lautet:
Page Fault (page not present) at 01014004h - EIP: 0000AD36h
Über die Info 01014000h 00000000h weiß man, dass nur bis 01013000h frames allokiert wurden. Daher muss man mindestens 0x1001 addieren, welches dann auf 0x2000 "aligned" wird. Dann klappt das.
So langsam bekomme ich das Thema Paging didaktisch in den Griff. Jetzt fehlt eigentlich nur noch die Darstellung des nicht-linearen Mappings.
-
Für das Laden von vorgefertigten File-Daten in den Speicher für die Ram Disk des VFS hat mir jemand einen möglichen Weg gewiesen, nämlich via NASM-Anweisung incbin und Linken mit ld. Diesen Befehl kannte ich bisher noch nicht.
-
Hier ein prinzipielles Beispiel mit Erzeugung mehrerer Tasks und Taskswitch:
http://www.henkessoft.de/OS_Dev/Downloads/35.zipAfter set_kernel_stack ==> tss_entry.esp0: 40101800h
> IRQ 127 <<<
Hello, user world!create a new process in a new address space
fork() returned: 00000002h and getpid() returned: 00000001hcreate a new process in a new address space
fork() returned: 00000003h and getpid() returned: 00000001hcreate a new process in a new address space
fork() returned: 00000004h and getpid() returned: 00000001hgetpid() 00000002h
getpid() 00000003h
getpid() 00000004h
getpid() 00000001h
getpid() 00000002hint retValFork1 = fork(); //create a new process in a new address space which is a clone of this int retValGetPid1 = getpid(); printformat("fork() returned: %x and getpid() returned: %x\n", retValFork1, retValGetPid1); //... task_switch(); printformat("getpid() %x\n", getpid()); sleepSeconds(3); task_switch(); //...
Den Scheduler kann man dann über den Timer aufrufen.
Mit Task Switches kann man schon auf einfachste Weise recht nette Sachen machen, hier ein Beispiel mit Farbwechsel (Farbe = Process ID) beim Tippen:
http://www.henkessoft.de/OS_Dev/Downloads/35a.zip (Programm)
http://www.henkessoft.de/OS_Dev/Downloads/task_switch_test.png (Test in Bochs)UCHAR c=0; while(TRUE) { if( k_checkKQ_and_print_char() ) { ++c; if(c>5) { c=0; settextcolor(4,0); printformat("\nT: %x H: %x WRITE: %i Read: %i ", pODA->pTailKQ, pODA->pHeadKQ, pODA->KQ_count_write, pODA->KQ_count_read); printformat("*T: %c %i *H: %c %i\n", *(pODA->pTailKQ),*(pODA->pTailKQ),*(pODA->pHeadKQ),*(pODA->pHeadKQ)); settextcolor(2,0); task_switch(); settextcolor(getpid(),0); } } }
Interessant ist, wenn man die Zeile task_switch(); settextcolor(getpid(),0); an eine andere Stelle in der while-Schleife setzt, dann gibt es einen eindrucksvollen "General protection fault":
http://en.wikipedia.org/wiki/General_protection_fault#Switching
..Nun muss ich mich noch mit dem Fileformat, dem Transfer in die RAM Disk und dem Zugriff im Programm via Virtual File System beschäftigen. Sobald das alles klappt und die Didaktik passt, werde ich stepwise am Tutorial weiter schreiben (verflixt viel Material und Background) und ein Basis Modell für die Weiterentwicklung von PrettyOS stabilisieren.
-
Erhard Henkes schrieb:
Nun muss ich mich noch mit dem Fileformat, dem Transfer in die RAM Disk und dem Zugriff im Programm via Virtual File System beschäftigen. Sobald das alles klappt und die Didaktik passt, werde ich stepwise am Tutorial weiter schreiben (verflixt viel Material und Background) und ein Basis Modell für die Weiterentwicklung von PrettyOS stabilisieren.
nun wird es auch an der zeit sein, dir grundsätzliche überlegungen zu machen, ob du dabeibleiben oder abweichen solltest.
nur ein kleines beispiel: ich bekomme als spielstandslader oder compilerbauer vom bs (win oder linux hier echt gleich) per filemapping daten hereingeschubst. Shade nannnte es dieser datenhaltung diesbezüglich afair NonCopyStrings, ich splitte bei zum beispiel immer bei \n und habe "zeilen", die aus struct{char *begin,*end} bestehen. das bs gibt mir einen bei read() z.B. 8K großen sektor un ich gebe ihn zurück, wenn ich ihn nicht mehr brauche. natürlich kann ich als old-style-lib ein kopierendes read() im userspace anbieten. vielleicht wäre ein no-copy-read verflixt viel schneller, wenn die anwendung das neue paradigma verwendet. in dieser richtung isses nicht nervig. andersrum schon: ich habe viele strings, ich habe ausschließlich stings mit begin/end in meiner anwendung (naja, c++ halt) und muß bei jedem syscall erstmal speicher für nullterminierten string anlegen, würg.
vielleicht wäre das an sich gar kein problem, wenn man strings von vorn herein mit begin/end auch im kernel schon angedacht hätte.
vielleicht wäre das ganze startup/shuutdown-geschmuse gar nicht notwendig, wenn ein prozess==programm leben würde, sobald es installiert ist und runterfahren/hochfahren nur betriebssystem-kacke wäre, die die anwendungen gar nicht sehen.
nur mal so als meinen kleinen einwurf. es könnte möglich sein, daß anscheinend voll verrückte konzepte aus versehen zugleich dir voll arbeit sparen, das BS schneller machen und für den anwendungsprogrammierer auch noch netter sind.hihi, ich möchte nicht in deinen schuhen stecken.
-
volkard schrieb:
nur ein kleines beispiel: ich bekomme als spielstandslader oder compilerbauer vom bs (win oder linux hier echt gleich) per filemapping daten hereingeschubst. Shade nannnte es dieser datenhaltung diesbezüglich afair NonCopyStrings, ich splitte bei zum beispiel immer bei \n und habe "zeilen", die aus struct{char *begin,*end} bestehen. das bs gibt mir einen bei read() z.B. 8K großen sektor un ich gebe ihn zurück, wenn ich ihn nicht mehr brauche.
hört sich gut an. eine proprietäre high-speed datenschnittstelle zwischen OS und user-mode hat vorteile, z.b. wenn irgendwann netzwerkprotokolle, filesystems, etc. dran sind, die dann bequem im userspace laufen könnten, was der stabilität des system zugute kommen würde. knackpunkt ist aber das zurückgeben der buffer ans system, es wäre ja doof, wenn die anwendung das vergisst und der kernel irgendwann 'out of memory' ist.
volkard schrieb:
hihi, ich möchte nicht in deinen schuhen stecken.
ich auch nicht, aber erhard hat durchhaltevermögen und auf den kopf gefallen ist er auch nicht.
-
Danke für den interessanten Einwurf.
hihi, ich möchte nicht in deinen schuhen stecken.
Das Problem ist, dass alles miteinander vernetzt ist, aber so ist es nun einmal.
-
Erhard Henkes schrieb:
Das Problem ist, dass alles miteinander vernetzt ist, aber so ist es nun einmal.
deswegen sollteste frühzeitig das ganze in überschaubare teilkomponenten zerlegen, KISS-prinzip, teile und herrsche und so.
-
Erhard Henkes schrieb:
hihi, ich möchte nicht in deinen schuhen stecken.
Das Problem ist, dass alles miteinander vernetzt ist, aber so ist es nun einmal.
hihi, ich möchte nicht in deinen schuhen stecken.
-
deswegen sollteste frühzeitig das ganze in überschaubare teilkomponenten zerlegen
Genau dies werde ich versuchen, soweit das möglich ist. Paging, Heap, Task Switching, User Mode vs Kernel Mode, Syscalls, VFS sind solche Einheiten, die allerdings zum einfachen Begreifen teilweise zu groß sind. Da versuche ich gerade, Unterelemente als elementare Module weiter heraus zu schneiden.
Noch wichtiger ist die Visualisierung / Verständlichmachung dessen, was passiert, wenn man dies oder jenes ändert, weil viele Leute beim Verstehen und Begreifen eher praktisch an die Dinge heran gehen.
..
Der Schwachpunkt von PrettyOS besteht momentan noch darin, dass noch kein Fileformat festgelegt wurde (jedoch kein Problem) und noch kein Mechanismus zum Übertragen von "Files" (Laden/Lesen Schreiben/Speichern), z.B. aus der RAM Disk in den Speicher und umgekehrt existiert. Sobald diese Mechanismen funktionieren, komme ich auf dieses Thema "proprietäre high-speed Datenschnittstelle zwischen OS und User Mode" zurück. Es geht nichts verloren. Wie sehen die entsprechenden Pendants bei Linux und Windows genau aus, damit ich das im Detail studieren kann?
-
Erhard Henkes schrieb:
Wie sehen die entsprechenden Pendants bei Linux und Windows genau aus, damit ich das im Detail studieren kann?
win haste ja schon gefunden. bei linux heißt die schlüsselfunktion mmap http://linux.die.net/man/3/mmap
-
Danke!
-
Erhard Henkes schrieb:
Wie sehen die entsprechenden Pendants bei Linux und Windows genau aus, damit ich das im Detail studieren kann?
http://www.i.u-tokyo.ac.jp/edu/training/ss/lecture/new-documents/Lectures/
unter: 10-LPC. auch der rest, z.b. memory management, dürfte dich auch interessieren.
-
@+fricky: Danke für den Link!
Momentan interessiert mich dies hier am meisten, da ich davon bisher nur einen Bruchteil habe, und mir genau der Rest fehlt:
http://www.i.u-tokyo.ac.jp/edu/training/ss/lecture/new-documents/Lectures/02-VirtualMemory/VirtualMemory.pdf
PrettyOS muss aber nicht wirklich performant sein, sondern vor allem verständlich, eben als Experimentier-Plattform geeignet. Ich bin mir noch nicht sicher, ob mir das gelingt, hängt davon ab, inwieweit mir geeignete Visualisierungs-Funktionen für die einzelnen Module und Exceptions gelingen.Gibt es eine Übersicht, wie man weitere Infos aus Registern erhält, um Exceptions möglichst vollständig zu analysieren? Dann könnte man diese Funktion, die bisher nur Page Faults genauer unter die Lupe nimmt, weiter ausbauen:
..
r->err_code und das Register cr2 dürften wohl der Schlüssel dazu sein. Wenn man beim "Spielen" mit dem Code in ckernel.c auf eine Exception trifft, sollte man heraus finden können, was man eigentlich falsch gemacht hat. Das ist momentan noch nicht ausreichend gegeben. Das ist aus meiner Sicht noch das Hauptproblem.