Autor Thema: API: Wie realisiert man es am besten?  (Gelesen 10195 mal)

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« am: 01. January 2010, 14:43 »
Hi
Ich beschäftige mich seit einigen Tagen mit der API meines Kernels. Leider bekomme ich mit jeder Lösung 1000 neue Probleme und alles ist irgendwie extrem aufwändig.

Meine bisherige Lösung, bzw. Lösungsansatz

Ein Prozess ruft eine C-Funktion auf - bsp.: APITEST("hello world");
APITEST selber ist aber in assembly realisiert - in APITEST werden nun die Argumente, welche sich ja auf dem Stack befinden, wiederum an eine neue Stackadresse kopiert (Als Argument der 0xFF-ISR), um dann int 0xFF aufzurufen.

Die "0xFF-ISR" erwartet die Argumente auf dem Stack, und ist ebenfalls in asm geschrieben, nur die Funktions-Nummer kommt per eax

Von dieser ISR geht es nun weiter: Die Argumente werden wieder an eine neue Position im Stack kopiert, und dann die eax - entsprechende C-Funktion aufgerufen.

kurz: C -----> ASM --int0xFF--> ASM -----> C

Dabei gibt es nun ein Probleme - der String "hello world" befindet sich im virtuellen Speicher des Prozesses, die Funktion zum ausgeben des Strings benötigt aber den virtuellen Speicher des Kernels (gut, das geht vielleicht auch ohne Kernelspeicher, aber spätestens bei Dateiarbeiten muss ich mit dem Speicher des Kernels arbeiten)

Lösung: ich wechsle auf das PD des Kernels und mappe die Page, auf der sich der String befindet.

Problem: Was ist, wenn mehrere Prozesse das gleiche vor haben - ich kann also nicht die Page an der selben virtuellen Adresse mappen, wie sie im Prozess liegt - dadurch muss ich also alle Pointer die ich bekomme umrechnen.


Meine Frage nun:
Wie realisiere ich eine API am besten, die ich sowohl von asm, als auch C aus gut ansprechen kann, und wie regle ich das mit den Speicherräumen?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 01. January 2010, 15:38 »
Die meisten Systeme haben sowas wie ein PD des Kernels überhaupt nicht. Der Kernel läuft dann immer im Kontext des aktuellen Prozesses und damit ist das Problem mehr oder weniger gelöst.

Wenn du das nicht machen willst, musst du wohl oder übel temporär mappen und die Pointer umrechnen. Der tyndur-Kernel hat für solche temporären Mappings eine Funktion, die eine physische Adresse und eine Länge nimmt, die passenden Pages an irgendeine freie Stelle mappt und einen Pointer auf die entsprechende virtuelle Adresse (nicht die Startadresse der Page, sondern gleich mit passendem Offset) zurückgibt. Das gleiche dann entsprechend fürs Freigeben.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #2 am: 01. January 2010, 17:47 »
Dadurch das mein Kernel ein eigenes PD hat, spare ich mir die PDs der Prozesse anzupassen, wenn ich im Kernel zum Eigenbedarf Speicher reserviere.
In die PDs der Prozesse werden dann nur die Speicherbereiche gemappt, die für Taskwechsel nötig sind, der Heap des Kernels ist für sie ja unwichtig. Nach dem erstellen eines Prozesses braucht dann im Bereich des Kernelspeichers nichts mehr am PD geändert werden.

Ich werd's dann wohl mit dem rummappen machen.

Das Problem mit dem zahlreichen kopieren der Argumente löse ich, indem ich nur noch die Adresse weiterreiche, an der die Argumente liegen.

Danke für die Antwort

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #3 am: 01. January 2010, 18:28 »
Ich persönlich hab es so gelöst, dass ganz am Anfang alle Page Tables des Kernelspaces (also für 0xC0000000 bis 0xFFFFFFFF bei mir) in dessen Page Directory eingetragen werden. Wenn ein neuer Prozess erstellt wird, dann wird dieser Bereich (also die oberen 256 Einträge) von diesem "Ur-Page-Directory" in das Page Directory des neuen Prozesses kopiert. Wenn nun irgendwas im Kernelspace gemappt wird, dann trägt man das in einer dieser Page Tables ein und das ändert sich dadurch in allen Prozessen gleichzeitig (weil dort ja überall die gleichen Page Tables eingetragen sind), ohne dass man deren Page Directory verändern müsste.
« Letzte Änderung: 01. January 2010, 18:30 von XanClic »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 01. January 2010, 20:15 »
Außer man braucht eine neue Page Table. ;)

Oder legst du gleich 256 Page Tables an und verschenkst das Megabyte halt, wenn es nicht genutzt wird?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #5 am: 01. January 2010, 21:38 »
Wie geschrieben, ich lege von vornherein alle 256 Page Tables an. Jo, dann ist das Megabyte weg. Aber ich bin sowieso nicht drauf aus, ein besonders speicherschonendes OS zu schreiben. :-D

Der Vorteil ist eben, dass ich mich nicht mit dem Updaten der Page Directories plagen muss.

Genauer gesagt sind es btw 255 Page Tables, weil ich den Platz der letzten Page Table für das Page Directory nehme (also verbrauche ich den Platz von 0x300000 bis 0x400000 für diese "initialen" Pagingstrukturen, dabei sind die ersten 4 kB für das initiale Page Directory (das dann später das des Idle Tasks ist) und die restlichen 255 * 4 kB für diese Page Tables. Also bleiben die 4 kB ab 0xFFFFF000 ungemappt.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 01. January 2010, 21:43 »
Na hoffentlich kommt Erik nicht in diesem Thread vorbei, der würde dir was erzählen. :-D
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 01. January 2010, 23:57 »
Hallo,


Na hoffentlich kommt Erik nicht in diesem Thread vorbei, der würde dir was erzählen. :-D
Was soll das heißen? :-o
So oder so ähnlich würd ich das auch machen wenn ich ein Flat-Memory-OS entwickeln würde. Schade ist nur das man so keine 4MB-Pages für den Kernel nutzen kann.


Aber ich bin sowieso nicht drauf aus, ein besonders speicherschonendes OS zu schreiben. :-D
RAM kostet ja heutzutage fast nichts mehr. Die Menge an RAM-Bytes pro Euro wächst zur Zeit jedenfalls schneller als die CPU-MIPS pro Euro.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 02. January 2010, 00:04 »
Echt? Ich bin von dir gewohnt, dass du schon etwas auf Effizienz achtest, und hätte erwartet, dass das auch auf Speicherverbrauch erweiterbar ist. ;)

In tyndur machen wir es dynamisch statt gleich alle Page Tables anzulegen, und das führt nicht zu größeren Verrenkungen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 02. January 2010, 00:23 »
Hallo,


Echt? Ich bin von dir gewohnt, dass du schon etwas auf Effizienz achtest, und hätte erwartet, dass das auch auf Speicherverbrauch erweiterbar ist. ;)
Es handelt sich einmalig um exakt ein einziges MByte, von dem man einen gewissen Teil so wieso braucht, ich denke das ist verschmerzbar. Es sei den man möchte nen alten 386 mit nur 4 MByte RAM auch als Zielplattform unterstützen.

In tyndur machen wir es dynamisch statt gleich alle Page Tables anzulegen, und das führt nicht zu größeren Verrenkungen.
Das heisst wenn der Kernel mehr Speicher braucht werden alle PDs aktualisiert? Ich bin ehrlich, das währ mir zu viel Arbeit in Relation für das eine bisschen Speicher.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 02. January 2010, 00:32 »
Kisten mit 4 MB RAM zu unterstützen ist auch schon schwierig genug ohne eins davon direkt zu verschenken. ;)

Wobei da ein Monolith wohl wieder im Vorteil wäre.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #11 am: 02. January 2010, 01:31 »
In tyndur machen wir es dynamisch statt gleich alle Page Tables anzulegen, und das führt nicht zu größeren Verrenkungen.
Das heisst wenn der Kernel mehr Speicher braucht werden alle PDs aktualisiert? Ich bin ehrlich, das währ mir zu viel Arbeit in Relation für das eine bisschen Speicher.
Nur wenn eine neue Page Table gebraucht wird, werden die PDs aktualisiert. Das passiert alle 4MB mal. Also praktisch garnicht.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 02. January 2010, 16:06 »
Hallo,


Das heisst wenn der Kernel mehr Speicher braucht werden alle PDs aktualisiert? Ich bin ehrlich, das währ mir zu viel Arbeit in Relation für das eine bisschen Speicher.
Damit meinte ich das es mir zu viel Tipp-Arbeit währe überhaupt Code für das aktualisieren aller PDs zu erstellen.
Der einzigste Grund für diesen Aufwand den ich akzeptieren würde währe die Verwendung von 4MByte Pages für den Kernel, das kann immerhin etwas (manchmal auch mehr) an Performance bringen.

.... Das passiert alle 4MB mal. Also praktisch garnicht.
Bei einem Micro-Kernel, dessen bescheidener Speichereigenbedarf zur Laufzeit offensichtlich auch nur wenig wächst, muss man doch kein ganzes Giga-Byte vorsehen. Da reichen doch bestimmt 64MByte, und damit 64kByte an Page-Tables, völlig aus. Schon ist die sogenannte Verschwendung wieder in einem Maß wo es sich wahrlich nicht lohnt extra Code dagegen zu schreiben. Als positiver Nebeneffekt wächst der virtuelle Adressraum für die Programme auf satte 3,75GByte an.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

ehenkes_

  • Beiträge: 3
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 13. February 2010, 06:37 »
Wieviel MB benötigen eure OS denn so als Minimum? Bei PrettyOS liegt der Wert so um 20 MB.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 13. February 2010, 10:34 »
Was gehört denn bei dir zum Minimum? Das Standardimage von tyndur bootet im qemu mit 5 MB bis in eine Shell, mit 6 MB kann man sogar kedit noch starten. ;)

Aber wenn man es drauf anlegt, dürfte man auch mit weniger auskommen können: Nur eine virtuelle Konsole, Netzwerk weglassen und solche Sachen... [edit: Ich hab mal testweise liballoc gepatcht, jetzt reichen auch 4 MB für die Shell]
« Letzte Änderung: 13. February 2010, 10:49 von taljeth »
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #15 am: 13. February 2010, 12:03 »
12MB für den kernel (3 4MB-Pages), darauf kommt dann der heap
Ich würd bei mir mal auf ~16MB schätzen, wobei das schon extrem knapp werden kann.


Da der thread grad wieder in Gebrauch ist schildere ich mal mein derzeitiges vorgehen bei der API:
Wie XanClic empfohlen hat, habe ich den kernel-speicher in alle Prozesse gemapped. Meine pageverwalltung arbeitet quasi nur mit virtuellen Adressen - sodass ich für Kernel und Prozesse die selben Funktionen verwenden kann.
Ich habe dem VMS in 3 teile unterteilt, GLOBAL (hier liegt u.a. der Kernel samt Heap), LOCAL (hier liegen die pages die nur für einen Prozess zugreifbar sein müssen) und einen dritten Bereich in dem die PT's und das PD gemapped wurde (für die pageverwaltung)

Zur Vereinfachung der pageverwaltung habe ich zudem festgelegt, dass wenn mehr als 4MB reserviert werden sollen, dieses in 4MB-Pages getan wird. Braucht man also 6MB bekommt man 2 4MB Pages.
Ist vom speicherverbrauch vielleicht nicht sehr effektiv, aber dafür ist es 1. Schneller, 2. Einfacher und dadurch Stabieler.

Bei der API habe ich mir eine liste gebaut, in der ich einfach nur neue Funktionen einfügen muss, So wie es bei týndur wenn ich mich nicht irre.

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #16 am: 13. February 2010, 13:00 »
Zitat von: ehenkes
Wieviel MB benötigen eure OS denn so als Minimum?
Aktuell komme ich bei paloxena3 mit 7 MB in eine Shell, aber das heißt nichts, weil noch nicht viel da ist. :wink:

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 13. February 2010, 13:23 »
Wofür haut ihr denn alle den ganzen Speicher raus? Ich dachte bisher immer, schon tyndur sei verschwenderisch, aber bisher sieht es nicht danach aus, dass andere Systeme mit weniger auskommen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #18 am: 13. February 2010, 14:02 »
Na ja, ich reserviere das erste MB komplett, das zweite für den Kernelcode, das dritte für den Stack, das vierte für Kernel-Page-Directory und -Page-Tables und ab dem fünften kommt dann die Bitmap für den PMM. Und danach kommt dann der dynamisch allokierte Rest.
« Letzte Änderung: 13. February 2010, 14:05 von XanClic »

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 14. February 2010, 00:25 »
Hallo,


ihre redet doch alle "nur" von einem OS mit einer Shell. Brauchen Eure OS dafür wirklich so viel Speicher? :-o
Ich sehe ja ein das die PD u.ä. einiges an physischen Speicher fressen aber doch nicht so viel. Ich hab mal große Programme für einen DOS-Extender (der ja was Speicherverwaltung/IRQ-Management usw. angeht einem OS schon recht nahe kommt) entwickelt und der hat kaum 400kBytes für sich selbst verbraucht. Errinnert sich den keiner mehr an das goldene Motto "640kByte sind genug für ...."? :-D


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

 

Einloggen