Hallo liebe Leute,
nach einigen vortragen auf der Uni zum Thema Betriebssystem, würde ich
gerne selber ein simples x86-OS schreiben. Ganz banal gehalten ohne GUI
nur commandline als Input also nur eine Tastatur und ein Bilschirm als
Peripherie. Als "Computer" würde ich den rasperry pi 3 nehmen.
Nun hänge ich allerdings bereits am virtuellen Speicher ;( Die Probleme
sind:
Wie steuert man möglichst vernünftig die MMU an
2) Ich habe jetzt in einer Seitentabelle die Werte [Nummer,
Prozess(zudem es gehört), Start, Zugriffshäufigkeit und Ende. wie
schaffe ich es nun, dass das laufende Programm nicht auf eine fremde
Seite zugreift?
3) Bzw wie ist der zugriff generell? Ich habe jetzt Programm bekommt
beim Start gesagt was seine high_adresse ist. Wenn es auf eine virtuelle
Speicherzelle zugreifen will setzt es einen Systemcall mit seiner
Prozessnummer, Adresse auf die es zugreifen will, lese/schreibbit.Das OS
nimmt den Call, schaut nach welche physische Adresse die Adresse X des
Programmes Y hat. Speichert den Wert zwischen und bringt ihn dann den
handler des Programmes zurück.
Und nochetwas, wie unterscheidet das OS ob in einer Zelle ein Befehl
oder eine Zahl steht?
Geht das nicht anders bzw schneller bzw schlauer&einfacher?
Wie macht das z.B.: MacOS?
Stimmt der Ansatz?
Danke,
Liebe Grüße,
Paul
Paul schrieb:> würde ich gerne selber ein simples x86-OS schreiben. [...]> Als "Computer" würde ich den rasperry pi 3 nehmen.
Fail: Der PI3 hat keinen x86-Prozessor.
> Stimmt der Ansatz?
Also wenn ich deine Fragen so lese dann wuerde ich empfehlen erstmal
zwei Nummern kleiner anzufangen. Du hast riesige Luecken bei den
Grundlagen.
Olaf
Hopsi,
tut mir leid ich hätte zuerst nachschauen sollen und dann posten ;).
Ok dann eben für z.B.: einen blanken Pc oder dass es für einen PC von
einem USB brotbar ist ;)
Lg
Du hast da was vollkommen durcheinander...
Fangen wir erstmal so an: Welche Programmiersprache beherrscht du bzw.
welche willst du nutzen?
Oder versuchst du grade über die sogenannte "Bash" zu programmieren?
Das ist nicht dafür gedacht. Die Bash führt in erster Linie nur
Programme aus.
Wenn du ein Kommandozeilenprogramms chreiben willst, hilft dir das
vielleicht. Die Programmiersprache C ist dafür recht gut geeignet:
http://www.circuitbasics.com/how-to-write-and-run-a-c-program-on-the-raspberry-pi/
Sobald das läuft, zieh dir einen allgemeinen C Crashkurs rein. Da
erfährst du wie du über die Kommandozeile, Interaktivität erreichst
(also nicht nur Text/Werte ausgeben, sondern auch einlesen).
EDIT:
Achsooo, du willst ein OS schreiben!
Nee, dann hat Olaf schon Recht. Das kann man ohne sehr direkte,
fachkundige Anleitung des Professors als durchschnittlicher Student eher
nicht. Man sollte dafür erst ein paar Jahre normale Programmiererfahrung
gesammelt haben.
Hi,
ich beherrsche C und Assembler schon ein paar Jährchen ;)
Mir ist nur unklar in welcher Struktur und Reihenfolge man das OS
aufbaut und halt das mit dem vm halt?
Danke und Lg
Paul schrieb:> Als "Computer" würde ich den rasperry pi 3 nehmen.
Da der kaum dokumentiert ist, keine allzu gute Idee. Viel einfacher geht
das z.B. beim Beaglebone Black, das ist ein weitgehend dokumentierter TI
Sitara am3358. Ein JTAG-Anschluss muss aber nachgerüstet werden. Mit ARM
statt x86 anzufangen ist nicht verkehrt, da man m.W. bei x86 noch viel
Legacy-Zeug mitschleppen muss.
Paul schrieb:> wie> schaffe ich es nun, dass das laufende Programm nicht auf eine fremde> Seite zugreift?
Die Seitentabelle wird der MMU mitgeteilt, und die sorgt dafür dass ein
Programm nur auf die dort eingestellten Seiten zugreifen kann. Falsche
Zugriffe führen zu einer Abort Exception.
Paul schrieb:> Wenn es auf eine virtuelle> Speicherzelle zugreifen will setzt es einen Systemcall mit seiner> Prozessnummer
Nein, es wäre doch ganz schön ineffizient wenn es für jeden Zugriff
einen Syscall machen müsste! Das kann gar nicht funktionieren, denn
selbst Zugriffe auf den Programmcode (Instruktionen) und den Stack gehen
ja über virtuelle Adressen. Nein, der User-Code greift "direkt" auf die
gewünschte Adresse zu, die MMU bildet die Adresse ab.
Paul schrieb:> Und nochetwas, wie unterscheidet das OS ob in einer Zelle ein Befehl> oder eine Zahl steht?
Was für eine Zelle? Das OS lädt Instruktionen in den einen Bereich und
Daten in einen anderen. Es teilt dem Prozessor mit, dass er die
Instruktionen ausführen möge. Man kann (versehentlich) auch Daten
"ausführen", was selten gut geht und ein Einfallstor für Exploits ist.
MMUs können das (teilweise) verhindern (NX-Bit).
Lies einfach mal im ARMv7A Architecture Reference Manual das Kapitel B3.
Das erklärt einiges.
Ansonsten: https://wiki.osdev.org/Expanded_Main_Pagehttps://github.com/allexoll/BBB-BareMetal
bei Github gibt es einen Haufen Mini/Simple x86 OS "Experimente"
z.B. das hier:
https://github.com/jbush001/os
und viele andere - vielleicht kannst du damit deine bisherigen
Kenntnisse erst mal prüfen
Vielleicht noch ne Runde kleiner anfangen und einen Scheduler für einen
Cortex-M3/4 schreiben. Erst kooperatives, dann präemptives Multitasking
implementieren.
Damit hat man dann das Herzstück und das wesentliche Grundverständnis.
Als nächstes auf ein System mit MMU wechseln.
Grund für meinen Vorschlag ist, dass ein RTOS auf einem M3 noch recht
übersichtlich ist, und es viele Beispiele gibt. Weiterhin wird man mit
DevBoards erschlagen, die meisst einen integrierten Debugger mitbringen,
so dass man auch mal ins System schauen kann. Auf X86 mit "printf" einen
Scheduler bauen, prost Mahlzeit :-)
Also bedeutet das, dass ich mich um das mapping virtuell zu physikalisch
überhaupt nicht sorgen muss?
Bzw.welches Programm welche "Pages" bekommt muss aber schon das OS
zuteilen oder auch MMU?
Ist für ein Programm der Anfang seines Speicherbereiches 0 oder weiß es
dass es die Adressen zwischen z.B.: 3-7 beutzt?
Lg
Eine ergängzung noch zum Virtual Memory. Dies wird komplett in Hardware
gelöst, ein Prozess fragt nach einer Speicheradresse. FÜr diesen
Prozess/Kontext gibt es im Speicher eine mehrstufige Tabelle, in der die
MMU selbständig nachschaut, welche reale Adresse dazugehört. Diese wird
dann ausgelesen und der CPU zugeführt.
Paul schrieb:> Also bedeutet das, dass ich mich um das mapping virtuell zu physikalisch> überhaupt nicht sorgen muss?
Du musst das Mapping festlegen, die Umsetzung macht die MMU.
Paul schrieb:> Bzw.welches Programm welche "Pages" bekommt muss aber schon das OS> zuteilen oder auch MMU?
Das macht das OS.
Paul schrieb:> Ist für ein Programm der Anfang seines Speicherbereiches 0 oder weiß es> dass es die Adressen zwischen z.B.: 3-7 beutzt?
Das kann das OS beliebig definieren. Die Abbildung
virtuelle->physikalische Pages kann sehr frei gestaltet werden. Du
kannst jedem Prozess den kompletten virtuellen Adressraum 0 bis (2^32)-1
zur Verfügung stellen und auf beliebige physikalische Adressen mappen,
du kannst z.B. die erste Page ausnehmen und als ungültig definieren
damit Null-Pointer-Zugriffe zu einem Absturz führen, du kannst
verschiedenen Programmen die selben Pages zuordnen damit z.B. mehrere
Instanzen des selben Programms nur 1x Programmspeicher belegen (Aber
Achtung: Page-Coloring-Problem bei VIPT-Caches beachten), du kannst
beliebig Lücken im virtuellen Adressraum lassen. Du kannst so etwas wie
ASLR umsetzen und jedem Prozess beim Starten eine andere Aufteilung des
virtuellen Adressraums verpassen oder definieren, dass bestimmte Dinge
immer an der selben virtuellen Adresse sind. Das Programm kann in seiner
ausführbaren Datei (z.B. ELF) seinen Einsprungpunkt an einer gewünschten
Adresse angeben oder das Betriebssystem erwartet diesen an einer
bestimmten Position usw usf. Das musst du dir alles überlegen.
Paul schrieb:> Also bedeutet das, dass ich mich um das mapping virtuell zu physikalisch> überhaupt nicht sorgen muss?
Doch, das ist die Aufgabe des OS.
> Bzw.welches Programm welche "Pages" bekommt muss aber schon das OS> zuteilen oder auch MMU?
Genau, das OS pflegt die entsprechenden Listen und konfiguriert die MMU
entsprechend. Eng verknüpft mit der MMU sind auch die Caches, die
ebenfalls konfiguriert werden müssen. Bei älteren ARM-Prozessoren waren
die Caches stets virtuell gemapt, d.h. bei Änderung der Page Tables
musste das OS sicherstellen, dass "dirty" Caches zurückgeschrieben
werden. Dieses Problem hat man nicht bei physikalisch gemappten Caches.
Ich empfehle äußerst dringend, zunächst die Caches vollständig zu
deaktivieren.
Für jeden Mikroprozessor bzw. dessen zugrundeliegende Architektur gibt
es auch entsprechende Dokumentation, in dem die MMU und Caches
ausführlich beschrieben sind. Das ist keine leichte Kost, denn man muss
sich bei jedem einzelnen Merkmal überlegen, warum der Hersteller genau
diesen Weg gegangen ist.
> Ist für ein Programm der Anfang seines Speicherbereiches 0 oder weiß es> dass es die Adressen zwischen z.B.: 3-7 beutzt?
Das OS legt das Speicherlayout für die Anwendungsadressräume fest. Die
Granularität von Speicherseiten wird durch die MMU und deren
Konfiguration bestimmt und liegt häufig bei Vielfachen von 256 Byte.
Eine ganz wichtige Designentscheidung besteht auch in der Festlegung, ob
sämtlicher Speicher für einen Anwendungsprozess gleich bei der Erzeugung
des Prozesses zugewiesen oder erst später angefordert werden soll. Bei
späterer Anforderung muss man entscheiden, ob dies durch einen
expliziten Betriebssystemaufruf oder für die Anwendung unbemerkt durch
den Page-Fault-Handler erfolgen soll. Letzteres wäre bei aktuellen
unixoiden Betriebssystemen die Regel.
> Eine ganz wichtige Designentscheidung besteht auch in der Festlegung, ob> sämtlicher Speicher für einen Anwendungsprozess gleich bei der Erzeugung
Und irgendwann kommt dann auch der Moment wo die Fachleute
unterschiedlicher Meinung sind. :-)
https://en.wikipedia.org/wiki/Tanenbaum–Torvalds_debate
Olaf