Autor Thema: Frage zu meinem Kerneldesign  (Gelesen 7189 mal)

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« am: 02. December 2008, 23:17 »
Nabend zusammen,

ich habe mir mal Gedanken über meinen Kernel gemacht.
Mein Kernel soll wirklich nur das Nötiggste machen.
 - GDT/IDT/ISR/IRQ/PIC/PIT initialisieren
 - den Scheduler bereitstellen
 - Methoden für den Speicher (memset, etc)
Der Rest soll über Treiber gemacht werden:
 - Dateisystem , Paging und alles was sonst noch an Treibern fehlt
Diese Treiber sollen erst nachgeladen werden (sprich nicht mitkompilieren).
Wie kann ich die denn zur Laufzeit laden?

Nun zu meinen Fragen:
Ist dieser Aufbau überhaupt sinnvoll?
Bei dem Scheduler habe ich ein paar Verständnisfragen:
 - Was brauch ich denn alles an Strukturen?
   Ich habe mir gedacht, dass ich einerseits einen Prioritätsparameter habe, dann habe    ich noch einen counter der die Rechenzeit mit zählt und dann die Strukturen für die Register und den Stack.
Wie rette ich den gesamten Prozessor in die Strukturen?
Mein Programm wird doch über einen Interrupt unterbrochen, wenn ich nun die Behandlungsroutine aufrufe steht in meinem PC doch schon eine andere Befehlsadresse. Wo bekomme ich die alte her, damit ich sie speichern kann?

Wenn mein Scheduler arbeitet muss ich doch ein paar Interrupts maskieren, oder?
Dachte jetzt mal an den PIT und Software-Interrupts.
Wie mache ich das?

Das war es erst einmal an Fragen.
Da kommen bestimmt noch mehr.

gruß,
rizor
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

jgraef

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 02. December 2008, 23:53 »
Nabend zusammen,

ich habe mir mal Gedanken über meinen Kernel gemacht.
Mein Kernel soll wirklich nur das Nötiggste machen.
 - GDT/IDT/ISR/IRQ/PIC/PIT initialisieren
 - den Scheduler bereitstellen
 - Methoden für den Speicher (memset, etc)
Ich denke du brauchst Sachen wie malloc() (womit eine Menge anderer Sachen verbunden sind)
Zitat
Der Rest soll über Treiber gemacht werden:
 - Dateisystem , Paging und alles was sonst noch an Treibern fehlt
Diese Treiber sollen erst nachgeladen werden (sprich nicht mitkompilieren).
Wie kann ich die denn zur Laufzeit laden?
ELF in den Speicher laden (deswegen wäre es außerdem günstig Paging im Kernel zu haben) und Symbole auflösen.
Zitat
Nun zu meinen Fragen:
Ist dieser Aufbau überhaupt sinnvoll?
Naja bis auf, dass ich Speicherverwaltung auch in den Kernel reinmachen würde, sieht das für mich zumindestens sinnvoll aus. Ist natürlich nicht besonders ausführlich, deswegen kann ich das nicht 100%ig beurteilen.
Zitat
Bei dem Scheduler habe ich ein paar Verständnisfragen:
 - Was brauch ich denn alles an Strukturen?
Du brauchst eine Struktur für einen Prozess. Diese Struktur muss sachen, wie Register und Speicherzuordnung (z.B Pagedir) enthalten. Aber auch Dinge wie Name, PID, Parent, Children, geöffnete Objekte (z.B Dateien) kann man reinmachen.
Zitat
   Ich habe mir gedacht, dass ich einerseits einen Prioritätsparameter habe, dann habe    ich noch einen counter der die Rechenzeit mit zählt und dann die Strukturen für die Register und den Stack.
Jo, wie ich oben gesagt habe, aber Speicher wäre noch wichtig.
Zitat
Wie rette ich den gesamten Prozessor in die Strukturen?
Mein Programm wird doch über einen Interrupt unterbrochen, wenn ich nun die Behandlungsroutine aufrufe steht in meinem PC doch schon eine andere Befehlsadresse. Wo bekomme ich die alte her, damit ich sie speichern kann?
Wenn der Interrupt aufgerufen wird, liegen einige Register (darunter auch EIP und ESP) auf dem Stack. Da kannst du die dann herholen und in die Struktur "retten".
Zitat

Wenn mein Scheduler arbeitet muss ich doch ein paar Interrupts maskieren, oder?
Nicht dass ich wüsste.
Zitat
Dachte jetzt mal an den PIT und Software-Interrupts.
Wie mache ich das?
Der PIT muss am Anfang ge-remappt werden. Bei mir ist er imho auf 0x20 bis 0x30 (0x00-0x1F sind Exceptions). Dann hast du da deine IRQs. Danach kommen bei mir ein paar andere Interrupts (APIC, unwichtig für dich). Und dann hab ich meinen Softwareinterrupt bei 0x37. Du kannst ihn natürlich auch woanders hinmachen (Linux hat ihn z.B bei 0x80). Du musst eigentlich nur den Interrupt in der IDT registrieren und den Handler zuweisen. Im Handler kannst du dann Daten (z.B welcher Syscall aufgerufen werden soll, usw.) aus dem Speicher des Prozesses oder aus den Registern holen.
Zitat
Das war es erst einmal an Fragen.
Da kommen bestimmt noch mehr.
Fragen sind bei uns immer willkommen, solange der Gegenüber vorher selbst nachdenkt :) (was, wie ich finde, du gut gemacht hast)

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 03. December 2008, 00:01 »
ich habe mir mal Gedanken über meinen Kernel gemacht.
Mein Kernel soll wirklich nur das Nötiggste machen.
 - GDT/IDT/ISR/IRQ/PIC/PIT initialisieren
 - den Scheduler bereitstellen
 - Methoden für den Speicher (memset, etc)
Der Rest soll über Treiber gemacht werden:
 - Dateisystem , Paging und alles was sonst noch an Treibern fehlt
Paging ist nicht irgendein optionales Zusatzfeature, das man bei Gelegenheit mal einbauen kann, sondern zentraler Bestandteil der Speicherverwaltung. Gehört also sicher nicht unter "irgendwelche nachladbare Treiber", sondern tatsächlich zum Nötigsten.

Ansonsten klingt dein Modell nach einem Mikrokernel (man könnte auch noch einen modularisierten Monolithen wie Linux reininterpretieren - in dem Fall könntest du Treiber zur Laufzeit laden, aber im Ende landet doch wieder alles im Kernel). Ein Mikrokernel wird hier von relativ vielen gemacht und funktioniert im allgemeinen auch ganz gut. Ist also keine ganz exotische Sache, wo dir niemand helfen könnte. Eine Sache, die du dann noch beachten müßtest, wäre daß die Treiber untereinander und mit den anderen Programmen auch kommunizieren müssen. Du bräuchtest also irgendeine Form von IPC.

Zitat
Diese Treiber sollen erst nachgeladen werden (sprich nicht mitkompilieren).
Wie kann ich die denn zur Laufzeit laden?
Von der Festplatte laden natürlich. Zugegeben, beim Plattentreiber wird das eher schwierig. GRUB erlaubt es dir, daß du deinem Kernel schon vom Bootloader Module in den Speicher laden läßt, die der Kernel dann nur noch starten muß. Das machst du mit den allennötigsten Treibern, um anschließend den Rest von Platte/CD/Floppy zu laden.

Zitat
Mein Programm wird doch über einen Interrupt unterbrochen, wenn ich nun die Behandlungsroutine aufrufe steht in meinem PC doch schon eine andere Befehlsadresse. Wo bekomme ich die alte her, damit ich sie speichern kann?
Die Rücksprungadresse landet auf dem Stack, und von dort kannst du sie natürlich auch auslesen.

Zitat
Wenn mein Scheduler arbeitet muss ich doch ein paar Interrupts maskieren, oder?
Dachte jetzt mal an den PIT und Software-Interrupts.
Im allgemeinen willst du im Kernel Interrupts sowieso komplett abschalten. Ansonsten wird alles deutlich komplizierter.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 03. December 2008, 00:36 »
Danke für eure Antworten.

Da sind mir jetzt noch ein paar Fragen in den Kopff geschossen:
- Wenn ich die Module vom Grub laden lasse, wie kann ich sie dann laden? (Wie sieht der "Befehl" aus)
- Sollte ich wirklich alle Interrupts deaktivieren?
Es kann doch ganz gut sein, wenn ich zum Beispiel IO-interrupts zulasse, damit ich zur Laufzeit bestimmte Prozesse vom wait in den ready-zustand schieben kann.
Das kann doch nur besser für die Laufzeit der Prozesse sein, oder?
Dabei drängt sich mir gleich noch eine neue Frage auf.
Ich habe 256 mögliche Interrupts die der Prozessor zuordnen kann, der PIC hat aber nur 15 Kanäle (Pic1 & Pic2).
Das bedeutet, dass ich meine Kanäle nicht eindeutig definieren kann.
Woher weiß ich nun, wenn aus Leitung 11 ein Interrupt kommt, von wem der Interrupt geworfen wurde?
Das ist ja extrem wichtig.

Danke für eure Hilfe.

gruß,
rizor

[edit]
könnt ihr mir eine seite nennen, die ext2 oder ext3 gut erklärt?
Muss ja wissen, wie ich den treiber zu schreiben habe.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 03. December 2008, 11:20 »
Da sind mir jetzt noch ein paar Fragen in den Kopff geschossen:
- Wenn ich die Module vom Grub laden lasse, wie kann ich sie dann laden? (Wie sieht der "Befehl" aus)
module /foo.elf

Vielleicht willst du dir auch mal den LOST-Code zum Vergleich anschauen. Gerade solche einfachen Fragen hast du dann schnell geklärt.

Zitat
- Sollte ich wirklich alle Interrupts deaktivieren?
Es kann doch ganz gut sein, wenn ich zum Beispiel IO-interrupts zulasse, damit ich zur Laufzeit bestimmte Prozesse vom wait in den ready-zustand schieben kann.
Das kann doch nur besser für die Laufzeit der Prozesse sein, oder?
Es ist den Aufwand nicht wert. Du müßtest an jeder beliebigen Stelle im Kernel darauf vorbereitet sein, daß ein Interrupt reinkommt und womöglich dieselben Variablen anfassen will. Das willst du nicht machen. Es reicht, wenn der Interrupt zuschlägt, wenn du wieder im Userspace bist.

Zitat
Ich habe 256 mögliche Interrupts die der Prozessor zuordnen kann, der PIC hat aber nur 15 Kanäle (Pic1 & Pic2).
Das bedeutet, dass ich meine Kanäle nicht eindeutig definieren kann.
Sicher, daß du hier die Zuordnung nicht falschrum machst? Von der 256 Interrupts, die die CPU kann, sind 16 von den IRQs besetzt. Dazu kommen noch Exceptions und Softwareinterrupts. Und selbst dann wirst du noch über 200 freie Interrupts haben.

Wo genau innnerhalb der 256 diese 16 anfangen, kannst du bei der Initialisierung des PIC festlegen.

Zitat
könnt ihr mir eine seite nennen, die ext2 oder ext3 gut erklärt?
Muss ja wissen, wie ich den treiber zu schreiben habe.
Du brauchst noch eine Weile, bis du dort bist. Im Wiki sind die entscheidenden Links aber auch drin.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 03. December 2008, 16:22 »
Wie kann ich mir das mit den Interrupts dann vorstellen?
Ich kann meine Prozesse dann in die Liste eintragen wenn ich möchte, oder?
Welche Art von Interrupt muss es denn dann sein, damit ich den Prozess anspreche?
Kann ich damit dann Abhängigkeiten realisieren, oder wie?
Also dass ein Prozess das Ergebnis eines anderen braucht um zu beginnen.
Ist das der Sinn dahinter?
Wenn ja, woher weiß mein Kernel, dass der Prozess auf den gewartet werden muss fertig ist?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

jgraef

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 03. December 2008, 19:29 »
Wie kann ich mir das mit den Interrupts dann vorstellen?
Ich kann meine Prozesse dann in die Liste eintragen wenn ich möchte, oder?
Welche Art von Interrupt muss es denn dann sein, damit ich den Prozess anspreche?
Kann ich damit dann Abhängigkeiten realisieren, oder wie?
Also dass ein Prozess das Ergebnis eines anderen braucht um zu beginnen.
Ist das der Sinn dahinter?
Wenn ja, woher weiß mein Kernel, dass der Prozess auf den gewartet werden muss fertig ist?
Also langsam wird's exotisch ;)
Interrupts haben eigentlich nichts mit Prozessen zu tun. Die brauchst nur den IRQ 0 für den Scheduler und dann wollen Prozesse eventuell einen Handler für IRQs anmelden.
Abhängigkeiten? Warten? Das ist eine ganz andere Ebene. Das wirst du dann wahrscheinlich über IPC realisieren.

Du musst jetzt erstmal grundlegende Dinge für deinen Kernel haben. Für den Anfang wäre eine Speicherverwaltung (phys und ein malloc() für den Kernel) nicht schlecht. Wenn du damit fertig bist, kannst du eine Prozessverwaltung bauen, wobei du dann auch den Speicher deiner Prozesse verwalten musst. Erst wenn dann dein erster Prozess läuft kannst du dir Gedanken darüber machen, wie diese miteinander kommunizieren.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 03. December 2008, 20:50 »
Achso.

Mal sehen ob ich es richtig verstanden habe.
Wenn einer meiner Prozesse einen Interrupt anmelden möchte, meldet er sich beim Scheduler der das dann alles verwaltet oder wie?
Ich weiß, dass ich ein wenig zu weit denke, aber ich möchte es in der Gesamtheit verstehen.
Aber wotu brauche ich dann die riesen Menge an möglichen IDT-Plätzen?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 03. December 2008, 21:00 »
Gar nicht. Die bleibt größtenteils leer. 32 Exceptions, 16 IRQs, ein Syscall und damit hast eigentlich alles, was du brauchst.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

 

Einloggen