| Zeile 25: | Zeile 25: | ||
===Voraussetzungen=== | ===Voraussetzungen=== | ||
| − | Obwohl dieses Wiki den Einstieg in Betriebssystementwicklung so einfach wie möglich machen will, ist Betriebssystementwicklung dennoch sehr komplex, und einige Fertigkeiten sind einfach nötig. Ich will nicht sagen, dass man die Fertigkeiten nicht durch | + | Obwohl dieses Wiki den Einstieg in Betriebssystementwicklung so einfach wie möglich machen will, ist Betriebssystementwicklung dennoch sehr komplex, und einige Fertigkeiten sind einfach nötig. Ich will nicht sagen, dass man die Fertigkeiten nicht durch „learning-by-doing“ erwerben kann, jedoch wird das bei diesem Thema sehr frustrierend. Außerdem wärst du dann allein, weil die meisten Forenmitglieder bei Erklärungen zu Betriebssystemtheorie nicht bei Adam und Eva anfangen können. |
====Unverzichtbar==== | ====Unverzichtbar==== | ||
* Programmiererfahrung! Wenn du noch nie ein Programm geschrieben hast, bist du hier ziemlich sicher falsch. Das Programmieren eines richtigen Betriebssystems ist keine Anfängerübung zum Erlernen des Programmierens, ein gewisser Level an Programmiererfahrungen ist dafür zwingend erforderlich. Wenn du erst einmal einen Einstieg in das Programmieren als solches suchst, dann werden dir die Lowlevel-Forenmitglieder sicher trotzdem dabei helfen, Tutorials und Ressourcen zu finden. | * Programmiererfahrung! Wenn du noch nie ein Programm geschrieben hast, bist du hier ziemlich sicher falsch. Das Programmieren eines richtigen Betriebssystems ist keine Anfängerübung zum Erlernen des Programmierens, ein gewisser Level an Programmiererfahrungen ist dafür zwingend erforderlich. Wenn du erst einmal einen Einstieg in das Programmieren als solches suchst, dann werden dir die Lowlevel-Forenmitglieder sicher trotzdem dabei helfen, Tutorials und Ressourcen zu finden. | ||
| − | * Gute Kenntnis des Systems und der benutzten Tools, also Compiler, Linker und deren Kollegen. Wenn du regelmäßig mit der Bedienung deines Betriebssystems oder der benötigten Programmierwerkzeuge kämpfst, dann ist es schwer, dabei Arbeit getan zu kriegen. Ein Windowsnutzer braucht eventuell sogar mehr Erfahrung als ein Linuxer, da sich manche Tools auf Windows zu Beginn recht zickig verhalten können. Auch die Zusammenhänge von Compiler | + | * Gute Kenntnis des Systems und der benutzten Tools, also Compiler, Linker und deren Kollegen. Wenn du regelmäßig mit der Bedienung deines Betriebssystems oder der benötigten Programmierwerkzeuge kämpfst, dann ist es schwer, dabei Arbeit getan zu kriegen. Ein Windowsnutzer braucht eventuell sogar mehr Erfahrung als ein Linuxer, da sich manche Tools auf Windows zu Beginn recht zickig verhalten können. Auch die Zusammenhänge von Compiler, Assembler und Linker sowie den dazwischen liegenden Dateiformaten (linkbare Objekt-Dateien und ausführbare Programm-Dateien) sollten zumindest in Grundzügen geläufig sein. |
* Neugier und Geduld. Vermutlich die heimlichen Kernqualifikationen jedes Programmierers. Ohne Neugier und Geduld wird es schwer, die Frustrationen der Betriebssystementwicklung zu überstehen. | * Neugier und Geduld. Vermutlich die heimlichen Kernqualifikationen jedes Programmierers. Ohne Neugier und Geduld wird es schwer, die Frustrationen der Betriebssystementwicklung zu überstehen. | ||
* Kenntnisse über die Funktionsweise eines Computers. Ein Betriebssystem hat die Aufgabe, den Anwendungsprogrammen einen funktionierenden und fairen Zugang zu den Ressourcen eines Computers zu ermöglichen. Dafür ist es natürlich von Vorteil, wenn man weiß, was den Computer in seinem Innersten zusammenhält. Du solltest also schon recht konkret wissen, was die einzelnen Komponenten eines Computers machen und wie diese zusammenspielen. | * Kenntnisse über die Funktionsweise eines Computers. Ein Betriebssystem hat die Aufgabe, den Anwendungsprogrammen einen funktionierenden und fairen Zugang zu den Ressourcen eines Computers zu ermöglichen. Dafür ist es natürlich von Vorteil, wenn man weiß, was den Computer in seinem Innersten zusammenhält. Du solltest also schon recht konkret wissen, was die einzelnen Komponenten eines Computers machen und wie diese zusammenspielen. | ||
| − | * Umrechnen zwischen Zahlensystemen. Beim OS-Dev muss man häufig zwischen Dezimal-, Hexadezimal-, Oktal- und Binärsystem umrechnen, um die richtigen Bits zu setzten | + | * Umrechnen zwischen Zahlensystemen. Beim OS-Dev muss man häufig zwischen Dezimal-, Hexadezimal-, Oktal- und Binärsystem umrechnen, um die richtigen Bits zu setzten bzw. zu löschen. Eine gute und kurze Anleitung dazu gibt es z. B. [http://www.linuxhilfen.org/c/c_aufsteiger_zahl.html hier]. Nachdem du verstanden hast wie es funktioniert und es mehrmals auf Papier geübt hast, kannst du natürlich auch z. B. den Windowstaschenrechner im „wissenschaftlichen Modus“ zum Umrechnen benutzen. Ab Windows 7 gibt es einen „Programmierer“-Modus, der das Umrechnen noch einfacher macht, indem man sogar einzelne Bits an- und abschalten kann. |
* Bitweise Operatoren. Man sollte wissen, wie man einzelne Bits innerhalb einer Variable löscht und setzt. Der Artikel [[Bitweise Operatoren]] bietet hier das nötige Basiswissen. | * Bitweise Operatoren. Man sollte wissen, wie man einzelne Bits innerhalb einer Variable löscht und setzt. Der Artikel [[Bitweise Operatoren]] bietet hier das nötige Basiswissen. | ||
====Hilfreich, aber nicht unbedingt nötig==== | ====Hilfreich, aber nicht unbedingt nötig==== | ||
* Unix-Kenntnisse. | * Unix-Kenntnisse. | ||
| − | * Assembler. Zwar braucht man nur einige Zeilen Assembler (wenn man es richtig macht), und das nötige Stück Assembler haben sich viele durch | + | * Assembler. Zwar braucht man nur einige Zeilen Assembler (wenn man es richtig macht), und das nötige Stück Assembler haben sich viele durch „learning-by-doing“ angeeignet, jedoch helfen Kenntnisse von Assembler enorm beim Verständnis. Es lohnt sich eigentlich bei jedem Projekt, eine Abstraktionsschicht tiefer schauen zu können. |
* Englisch. Handbücher, Spezifikationen und andere Dokumentation sind quasi nie auf Deutsch zu finden, und das, was man findet, ist häufig veraltet. Außerdem ist [http://wiki.osdev.org OSDev.org] oft noch besser als das Lowlevel-Wiki. Wir arbeiten dran ''*g*'' | * Englisch. Handbücher, Spezifikationen und andere Dokumentation sind quasi nie auf Deutsch zu finden, und das, was man findet, ist häufig veraltet. Außerdem ist [http://wiki.osdev.org OSDev.org] oft noch besser als das Lowlevel-Wiki. Wir arbeiten dran ''*g*'' | ||
| Zeile 52: | Zeile 52: | ||
Für welche Plattform du dein Betriebssystem schreiben möchtest, musst du auch überlegen, hier gibt es ebenfalls im Großen und Ganzen zwei Alternativen: | Für welche Plattform du dein Betriebssystem schreiben möchtest, musst du auch überlegen, hier gibt es ebenfalls im Großen und Ganzen zwei Alternativen: | ||
* Du nimmst den x86-PC, der mit extrem hoher Wahrscheinlichkeit bereits vor dir steht. Fast jeder programmiert für den x86-PC und du bekommst Unmengen an Beispielcode hier und im Internet. Dein Betriebssystem ist eins von vielen und im Forum oder im IRC wird dir fast jeder helfen können. Auf der anderen Seite ist die PC-Plattform nun schon über 30 Jahre gewachsen, einiges ist wild zusammengewürfelt und die einzelnen Komponenten benutzen teilweise sehr unterschiedliche Programmierparadigmen, je nach deren Alter. Du wirst dich mit seltsamen Dingen auseinander setzen müssen wie dem [[Real_Mode|Real-Mode]] bzw. [[Protected_Mode|Protected-Mode]] samt zugehöriger Segmentierung oder den unterschiedlichen [[Ring|Privilegstufen]]. Auch gibt es einige Hardwarekomponenten mehrfach (mit unterschiedlichem Alter und Funktionsumfang) wie z. B. [[PIC]] vs. [[APIC]] oder [[PIT]] vs. [[HPET]], da muss man sich oft überlegen, bis zu welchem Alter der x86-PCs das eigene Betriebssystem kompatibel sein soll, also welcher Umfang an Hardware (optional) unterstützt werden soll bzw. für das Betriebssystem als Voraussetzung gelten soll. | * Du nimmst den x86-PC, der mit extrem hoher Wahrscheinlichkeit bereits vor dir steht. Fast jeder programmiert für den x86-PC und du bekommst Unmengen an Beispielcode hier und im Internet. Dein Betriebssystem ist eins von vielen und im Forum oder im IRC wird dir fast jeder helfen können. Auf der anderen Seite ist die PC-Plattform nun schon über 30 Jahre gewachsen, einiges ist wild zusammengewürfelt und die einzelnen Komponenten benutzen teilweise sehr unterschiedliche Programmierparadigmen, je nach deren Alter. Du wirst dich mit seltsamen Dingen auseinander setzen müssen wie dem [[Real_Mode|Real-Mode]] bzw. [[Protected_Mode|Protected-Mode]] samt zugehöriger Segmentierung oder den unterschiedlichen [[Ring|Privilegstufen]]. Auch gibt es einige Hardwarekomponenten mehrfach (mit unterschiedlichem Alter und Funktionsumfang) wie z. B. [[PIC]] vs. [[APIC]] oder [[PIT]] vs. [[HPET]], da muss man sich oft überlegen, bis zu welchem Alter der x86-PCs das eigene Betriebssystem kompatibel sein soll, also welcher Umfang an Hardware (optional) unterstützt werden soll bzw. für das Betriebssystem als Voraussetzung gelten soll. | ||
| − | * Du nimmst eine andere Plattform. Das bedeutet mit hoher Wahrscheinlichkeit, dass erst mal Geld ausgegeben werden muss. Auch bist du dann ein Außenseiter und kaum jemand wird dir helfen können, wenn du mal auf (plattformspezifische) Probleme stößt, da bist du dann auf die (oft recht gute) Dokumentation (in Englisch) oder auf viele Versuche angewiesen. Dafür sind die meisten in Frage kommenden Plattformen recht gut | + | * Du nimmst eine andere Plattform. Das bedeutet mit hoher Wahrscheinlichkeit, dass erst mal Geld ausgegeben werden muss. Auch bist du dann ein Außenseiter und kaum jemand wird dir helfen können, wenn du mal auf (plattformspezifische) Probleme stößt, da bist du dann auf die (oft recht gute) Dokumentation (in Englisch) oder auf viele Versuche angewiesen. Dafür sind die meisten in Frage kommenden Plattformen recht gut ''„aus einem Guss“'' und auch sehr deutlich weniger komplex als der x86-PC. Es gibt auch deutlich weniger Stolperfallen und andere Merkwürdigkeiten. Ebenfalls sind die Programmierparadigmen für die einzelnen Hardwarekomponenten auf den Plattformen meist in sich stimmig und recht modern, die meisten alternativen Plattformen sind eben sehr viel jünger als der x86-PC. Wenn du ein Betriebssystem für Spielkonsolen oder SmartPhones entwickeln möchtest dann wirst du mehr mit den Sicherungsmechanismen der Hersteller als mit der Plattform als solches kämpfen, die Hersteller mögen es in der Regel gar nicht, wenn der ''zahlende'' Kunde die Geräte anders benutzen will, als der Hersteller sich das vorstellt. |
Die Mitglieder der Lowlevel-Community entwickeln ihre Betriebssysteme in aller Regel für den x86-PC, Ausnahmen gibt es da fast keine. Auch (fast) das gesamte Wiki hier bezieht sich ausschließlich auf den x86-PC. | Die Mitglieder der Lowlevel-Community entwickeln ihre Betriebssysteme in aller Regel für den x86-PC, Ausnahmen gibt es da fast keine. Auch (fast) das gesamte Wiki hier bezieht sich ausschließlich auf den x86-PC. | ||
===Entwicklungsumgebung und Tools=== | ===Entwicklungsumgebung und Tools=== | ||
| − | Um dein eigenes Betriebssystem zu entwickeln, brauchst du ein paar Werkzeuge. Du musst dir eine Buildumgebung aufbauen (was je nach Betriebssystem unterschiedlich komplex ist), du brauchst einen Editor und einen Emulator. All das wird im '''[[Teil_1_-_Entwicklungsumgebung|ersten Teil]]''' der Tutorial-Reihe | + | Um dein eigenes Betriebssystem zu entwickeln, brauchst du ein paar Werkzeuge. Du musst dir eine Buildumgebung aufbauen (was je nach Betriebssystem unterschiedlich komplex ist), du brauchst einen Editor und einen Emulator. All das wird im '''[[Teil_1_-_Entwicklungsumgebung|ersten Teil]]''' der Tutorial-Reihe „OS-Dev für Einsteiger“ erklärt. |
==Wo anfangen?== | ==Wo anfangen?== | ||
| Zeile 63: | Zeile 63: | ||
Dein eigenes Betriebssystem möchte am Anfang irgendwie von der Festplatte oder Diskette in den Speicher geladen werden, bevor es irgendwas macht. Daher brauchst du einen Bootloader. | Dein eigenes Betriebssystem möchte am Anfang irgendwie von der Festplatte oder Diskette in den Speicher geladen werden, bevor es irgendwas macht. Daher brauchst du einen Bootloader. | ||
| − | Hier gibt es die großen zwei Möglichkeiten, etwas fertiges zu nehmen oder selbst einen Bootloader zu schreiben. Ein guter Bootloader ist ein Projekt für sich, daher empfehle ich grundsätzlich, [[GRUB]] zu benutzen und sich auf das eigentliche Betriebssystem zu konzentrieren. [[GRUB]] lädt dir deinen [[Kernel]] und möglicherweise weitere Module vom Dateisystem auf der Platte oder Diskette, initialisiert dir den [[Protected Mode]], bietet ein Bootmenü und einiges mehr. Eine | + | Hier gibt es die großen zwei Möglichkeiten, etwas fertiges zu nehmen oder selbst einen Bootloader zu schreiben. Ein guter Bootloader ist ein Projekt für sich, daher empfehle ich grundsätzlich, [[GRUB]] zu benutzen und sich auf das eigentliche Betriebssystem zu konzentrieren. [[GRUB]] lädt dir deinen [[Kernel]] und möglicherweise weitere Module vom Dateisystem auf der Platte oder Diskette, initialisiert dir den [[Protected Mode]], bietet ein Bootmenü und einiges mehr. Eine detailliertere Erklärung warum hier GRUB empfohlen wird findet sich [[Grand Unified Bootloader#Warum GRUB? | hier]]. |
Die folgenden beiden Artikel werden dir bei den ersten Schritten mit [[GRUB]] helfen: | Die folgenden beiden Artikel werden dir bei den ersten Schritten mit [[GRUB]] helfen: | ||
* [[C-Kernel mit GRUB]] | * [[C-Kernel mit GRUB]] | ||
| − | * [[GRUB-Image erstellen]] (Falls Du Windows benutzt, ist es vermutlich einfacher, ein vorhandenes GRUB-Image z. | + | * [[GRUB-Image erstellen]] (Falls Du Windows benutzt, ist es vermutlich einfacher, ein vorhandenes GRUB-Image z. B. von [[týndur]] zu nehmen und den Kernel durch den eigenen zu ersetzen) |
Wenn du trotz diesen Vorteilen darauf bestehst, deinen Bootloader selbst zu schreiben – so sei es. In den ersten Ausgaben des [[:Kategorie:Magazin|Magazins]] findest du die dazu nötigen Informationen. In den folgenden Abschnitten gehe ich allerdings davon aus, dass [[GRUB]] benutzt wird. Du solltest also sicherstellen, dass du eine vergleichbare Umgebung herstellst – insbesondere, dass du im [[Protected Mode]] bist. | Wenn du trotz diesen Vorteilen darauf bestehst, deinen Bootloader selbst zu schreiben – so sei es. In den ersten Ausgaben des [[:Kategorie:Magazin|Magazins]] findest du die dazu nötigen Informationen. In den folgenden Abschnitten gehe ich allerdings davon aus, dass [[GRUB]] benutzt wird. Du solltest also sicherstellen, dass du eine vergleichbare Umgebung herstellst – insbesondere, dass du im [[Protected Mode]] bist. | ||
==== Äh ja, nochmal auf Deutsch bitte ==== | ==== Äh ja, nochmal auf Deutsch bitte ==== | ||
| − | Im '''[[Teil_4_-_Hello_World|vierten Teil]]''' der Reihe | + | Im '''[[Teil_4_-_Hello_World|vierten Teil]]''' der Reihe „OS-Dev für Einsteiger“ wird genau erklärt, wie du dir einen einfachen Kernel in C und mit GRUB aufbaust. Du wirst auch auf etwas [[Assembler]] stoßen. Solltest du kein Assembler beherrschen, keine Bange: Du brauchst nur ganz wenig für die Betriebssystementwicklung. Wenn du keinen Plan hast, wie du in Assembler programmierst, dann lies dir den '''[[Teil_2_-_Assembler_101|zweiten Teil]]''' des Reihe „OS-Dev für Einsteiger“ durch, dort bekommst du das benötigte Wissen, um den minimalen Assembler-Teil zu verstehen. |
===Hello World und weiter=== | ===Hello World und weiter=== | ||
| − | Die allererste Aufgabe für ein neues Betriebssystem ist es selbstverständlich, ein | + | Die allererste Aufgabe für ein neues Betriebssystem ist es selbstverständlich, ein „Hello world!“ auf den Bildschirm auszugeben. Wenn du nach dem oben genannten Artikel vorgegangen bist, hast du diesen Schritt schon erreicht. Wenn nicht: Text gibst du aus, indem du in den Videospeicher schreibst. Er beginnt für den Textmodus an der Adresse 0xB8000 und enthält für jedes Zeichen (insgesamt 80×25) auf dem Bildschirm je zwei Bytes. Das erste enthält den ASCII-Code des Zeichens selbst, das zweite Attribute wie Farbe. Experimentiere am besten ein bisschen damit herum. (Ausführlicher steht es im Artikel [[Textausgabe]]) |
Hey, mein Kernel läuft und gibt was aus, vielleicht wäre jetzt der Grafikmodus...? Nein! Ein wesentlicher Grund dafür ist, dass du in der nächsten Zeit viele kritische Änderungen und dabei auch viele Fehler machen wirst. Du wirst daher um [[Debugging]] nicht herumkommen. Am einfachsten geht das über Textausgaben, die leider im Grafikmodus nicht mehr ganz so leicht gehen. | Hey, mein Kernel läuft und gibt was aus, vielleicht wäre jetzt der Grafikmodus...? Nein! Ein wesentlicher Grund dafür ist, dass du in der nächsten Zeit viele kritische Änderungen und dabei auch viele Fehler machen wirst. Du wirst daher um [[Debugging]] nicht herumkommen. Am einfachsten geht das über Textausgaben, die leider im Grafikmodus nicht mehr ganz so leicht gehen. | ||
| Zeile 95: | Zeile 95: | ||
Wenn du die GDT aufgebaut hast, kannst du sie anschließend laden. Das ist einer der wenigen Fälle, wo du tatsächlich Assembler brauchst. Wenn du C benutzt, könnte dir der Artikel über [[Inline-Assembler mit GCC]] helfen. Ansonsten schlag in der Dokumentation deines Compilers nach, wie es dort funktioniert. | Wenn du die GDT aufgebaut hast, kannst du sie anschließend laden. Das ist einer der wenigen Fälle, wo du tatsächlich Assembler brauchst. Wenn du C benutzt, könnte dir der Artikel über [[Inline-Assembler mit GCC]] helfen. Ansonsten schlag in der Dokumentation deines Compilers nach, wie es dort funktioniert. | ||
| − | Anschließend musst du die Segmentregister neu laden, damit die GDT auch benutzt wird. An dieser Stelle zeigt sich dann, ob du es richtig gemacht hast. Wenn die Einträge in deiner GDT falsch sind, und beispielsweise das Codesegment nicht korrekt ist, wirst du mit höchster Wahrscheinlichkeit einen GPF auslösen. GPF steht übrigens für ''General Protection Fault'' und ist dir vielleicht als ''Allgemeine Schutzverletzung'' besser bekannt. Weil du noch keine [[Exception | + | Anschließend musst du die Segmentregister neu laden, damit die GDT auch benutzt wird. An dieser Stelle zeigt sich dann, ob du es richtig gemacht hast. Wenn die Einträge in deiner GDT falsch sind, und beispielsweise das Codesegment nicht korrekt ist, wirst du mit höchster Wahrscheinlichkeit einen GPF auslösen. GPF steht übrigens für ''General Protection Fault'' und ist dir vielleicht als ''Allgemeine Schutzverletzung'' besser bekannt. Weil du noch keine [[Exception]]s verarbeitest, wird das zu einem ''Triple Fault'' führen, was auf einem echten PC einen Reset bewirkt. |
===Interrupts=== | ===Interrupts=== | ||
| − | Hast du die GDT gemeistert? Glückwunsch. Aber freu dich nicht zu früh, wir haben noch mehr Tabellen im Angebot. Die zweite Tabelle, die du unbedingt benötigst, ist die Interrupt Descriptor Table ([[IDT]]). Wenn irgendein Stück Hardware melden möchte, dass irgendetwas passiert ist (z. | + | Hast du die GDT gemeistert? Glückwunsch. Aber freu dich nicht zu früh, wir haben noch mehr Tabellen im Angebot. Die zweite Tabelle, die du unbedingt benötigst, ist die Interrupt Descriptor Table ([[IDT]]). Wenn irgendein Stück Hardware melden möchte, dass irgendetwas passiert ist (z. B. eine Taste gedrückt wurde), schickt es im Allgemeinen einen [[Interrupt]] mit einer mehr oder weniger eindeutigen Nummer. In der IDT weist du jedem Interrupt eine Funktion in deinem Kernel zu, die aufgerufen wird, wenn der Interrupt ankommt. |
Auch zur IDT kannst du die im vorigen Abschnitt verlinkten Seiten befragen. | Auch zur IDT kannst du die im vorigen Abschnitt verlinkten Seiten befragen. | ||
| − | Neben den genannten Hardwareinterrupts gibt es noch weitere. Die wichtigsten davon sind [[Exception | + | Neben den genannten Hardwareinterrupts gibt es noch weitere. Die wichtigsten davon sind [[Exception]]s, die aufgerufen werden, wenn etwas schiefgeht (z. B. Division durch Null oder ein Speicherzugriff ohne Berechtigung) und Softwareinterrupts, die von einem Programm ausgelöst werden, z. B. um Funktionen des Kernels aufzurufen. |
| − | Wenn du die IDT fertig eingerichtet hast, kannst du sie am besten testen, indem du entweder eine Exception provozierst oder einen Softwareinterrupt auslöst. Bevor du die Hardwareinterrupts mit dem Assemblerbefehl sti anschaltest, solltest du nämlich erst noch den [[PIC]] programmieren, so dass die IRQs (das sind genau die Hardwareinterrupts) beispielsweise auf die Interrupts 0x20 bis 0x2f legst (bis 0x1f liegen schon die Exceptions und du willst IRQs ja von Exceptions unterscheiden können). | + | Wenn du die IDT fertig eingerichtet hast, kannst du sie am besten testen, indem du entweder eine Exception provozierst oder einen Softwareinterrupt auslöst. Bevor du die Hardwareinterrupts mit dem Assemblerbefehl ''sti'' anschaltest, solltest du nämlich erst noch den [[PIC]] programmieren, so dass die IRQs (das sind genau die Hardwareinterrupts) beispielsweise auf die Interrupts 0x20 bis 0x2f legst (bis 0x1f liegen schon die Exceptions und du willst IRQs ja von Exceptions unterscheiden können). |
* [[Programmable Interrupt Controller]] | * [[Programmable Interrupt Controller]] | ||
| Zeile 111: | Zeile 111: | ||
=== Hm, ja, anschauliches Beispiel? === | === Hm, ja, anschauliches Beispiel? === | ||
| − | Im '''[[Teil_5_-_Interrupts|fünften Teil]]''' der Reihe | + | Im '''[[Teil_5_-_Interrupts|fünften Teil]]''' der Reihe „OS-Dev für Einsteiger“ wird das Einrichten einer GDT sowie das Einrichten einer IDT und das Aktivieren von Interrupts und deren Behandlung noch einmal erklärt. Wenn du die Artikel zur [[GDT]] und [[IDT]] gelesen hast, wird dir schnell der Zusammenhang klar. |
==Der eigentliche Kernel== | ==Der eigentliche Kernel== | ||
| Zeile 119: | Zeile 119: | ||
Unter der ''Architektur'' deines Betriebssystem ist die Art und Weise zu verstehen, wie die Komponenten deines Systems zusammenspielen. Bevor du anfängst, Code für die eigentliche Funktionalität des Kernels zu schreiben, solltest du dir klar sein, in welche Richtung die Reise gehen soll. | Unter der ''Architektur'' deines Betriebssystem ist die Art und Weise zu verstehen, wie die Komponenten deines Systems zusammenspielen. Bevor du anfängst, Code für die eigentliche Funktionalität des Kernels zu schreiben, solltest du dir klar sein, in welche Richtung die Reise gehen soll. | ||
| − | * Die allerwichtigste Entscheidung, die das Aussehen deines Betriebssystems am schwerwiegendsten beeinflussen wird, ist die Entscheidung zwischen [[Monolithischer Kernel|monolithischem Kernel]] (die Hardwaretreiber sind alle im Kernel) und [[Microkernel]] (der Kernel macht nur das notwendigste, Treiber sind eigenständige [[Userspace]]-Prozesse) – oder natürlich beliebiger Mischformen davon, z. | + | * Die allerwichtigste Entscheidung, die das Aussehen deines Betriebssystems am schwerwiegendsten beeinflussen wird, ist die Entscheidung zwischen [[Monolithischer Kernel|monolithischem Kernel]] (die Hardwaretreiber sind alle im Kernel) und [[Microkernel]] (der Kernel macht nur das notwendigste, Treiber sind eigenständige [[Userspace]]-Prozesse) – oder natürlich beliebiger Mischformen davon, z. B. ein modularisierter Monolith wie [[Linux]]. |
* Besonders beim Microkernel ist eine zentrale Frage, wie die [[Interprozesskommunikation]] aussehen soll. Auch bei einem monolithischen Kernel ist es kein Fehler, sich diese Frage zu stellen, auch wenn sie eher nachrangig ist. | * Besonders beim Microkernel ist eine zentrale Frage, wie die [[Interprozesskommunikation]] aussehen soll. Auch bei einem monolithischen Kernel ist es kein Fehler, sich diese Frage zu stellen, auch wenn sie eher nachrangig ist. | ||
| − | * Wie soll die Schnittstelle der Programme zum Kernel aussehen? (z. | + | * Wie soll die Schnittstelle der Programme zum Kernel aussehen? (z. B. [[Syscall]]s) |
===Die Aufgaben des Kernels=== | ===Die Aufgaben des Kernels=== | ||
| − | Bevor du dir anschaust, welche Funktionen dein Kernel bieten soll, versichere dich, dass du weißt, was ein [[Kernel]] überhaupt ist. Ja, klar, er ist der Kern des Betriebssystems. Und weiter? Seine zentrale Aufgabe ist es, die Ressourcen des Systems zu verwalten – z. | + | Bevor du dir anschaust, welche Funktionen dein Kernel bieten soll, versichere dich, dass du weißt, was ein [[Kernel]] überhaupt ist. Ja, klar, er ist der Kern des Betriebssystems. Und weiter? Seine zentrale Aufgabe ist es, die Ressourcen des Systems zu verwalten – z. B. den laufenden Programmen Speicher zuzuteilen. |
| − | Im Allgemeinen wird für Betriebssysteme im [[Protected Mode]] ein Modell verwendet, in dem der Kernel in [[Ring]] 0 (Kernel Mode) und alle Programme in Ring 3 (User Mode) laufen. Als grobe Richtung kannst du dir merken, dass der Kernel alles das ist, was in Ring 0 läuft. Wenn ein User-Mode-Programm Betriebssystemfunktionen benötigt (z. | + | Im Allgemeinen wird für Betriebssysteme im [[Protected Mode]] ein Modell verwendet, in dem der Kernel in [[Ring]] 0 (Kernel Mode) und alle Programme in Ring 3 (User Mode) laufen. Als grobe Richtung kannst du dir merken, dass der Kernel alles das ist, was in Ring 0 läuft. Wenn ein User-Mode-Programm Betriebssystemfunktionen benötigt (z. B. mehr Speicher), ruft es den Kernel auf. |
Was sind nun also die Funktionen, die ein Kernel im Allgemeinen bietet? | Was sind nun also die Funktionen, die ein Kernel im Allgemeinen bietet? | ||
* [[Speicherverwaltung]]: Programme und höchstwahrscheinlich auch der Kernel selbst müssen zur Laufzeit dynamisch Speicher reservieren können. Die Speicherverwaltung im Kernel arbeitet üblicherweise nicht mit beliebigen anforderbaren Größen, sondern mit Blöcken von 4 Kilobytes, sogenannten ''Speicherseiten'' (engl. ''Pages''). Man unterscheidet dabei zwischen [[Speicherverwaltung#Physische_Speicherverwaltung | physischer]] und [[Speicherverwaltung#virtuelle_Speicherverwaltung | virtueller Speicherverwaltung]]. | * [[Speicherverwaltung]]: Programme und höchstwahrscheinlich auch der Kernel selbst müssen zur Laufzeit dynamisch Speicher reservieren können. Die Speicherverwaltung im Kernel arbeitet üblicherweise nicht mit beliebigen anforderbaren Größen, sondern mit Blöcken von 4 Kilobytes, sogenannten ''Speicherseiten'' (engl. ''Pages''). Man unterscheidet dabei zwischen [[Speicherverwaltung#Physische_Speicherverwaltung | physischer]] und [[Speicherverwaltung#virtuelle_Speicherverwaltung | virtueller Speicherverwaltung]]. | ||
| − | ** Ein anschauliches Beispiel zur Implementierung einer physischen Speicherverwaltung wird im '''[[Teil_7_-_Physische_Speicherverwaltung|siebten Artikel]]''' der Reihe | + | ** Ein anschauliches Beispiel zur Implementierung einer physischen Speicherverwaltung wird im '''[[Teil_7_-_Physische_Speicherverwaltung|siebten Artikel]]''' der Reihe „OS-Dev für Einsteiger“ gegeben |
* [[Prozessverwaltung]]: Ein Betriebssystem hat diese Bezeichnung nur verdient, wenn es Programme ausführen kann. Zur Prozessverwaltung gehören Funktionen wie das Starten und Beenden von Prozessen, aber im weiteren Sinne auch [[Multitasking]], also das Umschalten zwischen den einzelnen Prozessen. Neben [[Prozess|Prozessen]] möchtest du eventuell auch [[Thread|Threads]] unterstützen. | * [[Prozessverwaltung]]: Ein Betriebssystem hat diese Bezeichnung nur verdient, wenn es Programme ausführen kann. Zur Prozessverwaltung gehören Funktionen wie das Starten und Beenden von Prozessen, aber im weiteren Sinne auch [[Multitasking]], also das Umschalten zwischen den einzelnen Prozessen. Neben [[Prozess|Prozessen]] möchtest du eventuell auch [[Thread|Threads]] unterstützen. | ||
| − | * [[Interprozesskommunikation]]: Je nach Architektur des Betriebssystem extrem wichtig bis | + | * [[Interprozesskommunikation]]: Je nach Architektur des Betriebssystem extrem wichtig bis erst einmal völlig nebensächlich. Es geht dabei darum, dass zwei Programme Informationen austauschen können, z. B. durch Senden von Nachrichten oder Aufruf von Funktionen des anderen Programms. |
* [[Treiber|Hardwaretreiber]]: Jeder Kernel enthält auch Hardwaretreiber. Je nach Architektur gehören dabei alle, manche oder so gut wie keine Treiber zum Kernel. | * [[Treiber|Hardwaretreiber]]: Jeder Kernel enthält auch Hardwaretreiber. Je nach Architektur gehören dabei alle, manche oder so gut wie keine Treiber zum Kernel. | ||
* Den Bootprozess anstoßen. Nachdem der Kernel sich selbst initialisiert hat, lädt er in irgendeiner Form ein erstes Programm (unter Linux ''init'') und startet es. | * Den Bootprozess anstoßen. Nachdem der Kernel sich selbst initialisiert hat, lädt er in irgendeiner Form ein erstes Programm (unter Linux ''init'') und startet es. | ||
| Zeile 140: | Zeile 140: | ||
===Schnittstelle zum Userspace=== | ===Schnittstelle zum Userspace=== | ||
| − | Auch der tollste Kernel mit [[Multitasking]]-Unterstützung bringt dir natürlich herzlich wenig, wenn die laufenden Programme nicht mit dem Benutzer interagieren können. Um den Programmen, die ja in einem eigenen Adressraum laufen und meist keinen direkten Zugriff auf die Hardware haben, diese Möglichkeit zu bieten, muss der Kernel eine entsprechende Schnittstelle, üblicherweise in Form von [[Syscall | + | Auch der tollste Kernel mit [[Multitasking]]-Unterstützung bringt dir natürlich herzlich wenig, wenn die laufenden Programme nicht mit dem Benutzer interagieren können. Um den Programmen, die ja in einem eigenen Adressraum laufen und meist keinen direkten Zugriff auf die Hardware haben, diese Möglichkeit zu bieten, muss der Kernel eine entsprechende Schnittstelle, üblicherweise in Form von [[Syscall]]s, anbieten. Wie diese Schnittstelle genau aussieht, hängt von deiner gewählten Architektur ab. Bei einem Monolithen wird die Schnittstelle eher breit ausfallen, und beispielsweise Funktionen für das Arbeiten mit Dateien mitbringen, während bei einem Mikrokernel vor allem die Funktionen für die [[Interprozesskommunikation]] im Zentrum stehen werden. |
==== Da habt ihr doch sicher auch was in eurer Reihe, oder? ==== | ==== Da habt ihr doch sicher auch was in eurer Reihe, oder? ==== | ||
| − | Na klar. Im '''[[Teil_6_-_Multitasking|sechsten Teil]]''' der Reihe | + | Na klar. Im '''[[Teil_6_-_Multitasking|sechsten Teil]]''' der Reihe „OS-Dev für Einsteiger“ wird das Implementieren von Multitasking per [[TSS]] anschaulich und mit Codebeispielen erklärt. |
===Treiber=== | ===Treiber=== | ||