Autor Thema: Flexibles und einfaches Prozess erzeugen  (Gelesen 27224 mal)

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« am: 14. October 2011, 21:11 »
Ich wollte keine ewig alten Threads aus der Versenkung holen, deswegen mache ich mal nen neuen auf, auch wenn das Thema (Prozesserstellung) schon ein paar Mal diskutiert wurde.

Da ich bisher immer noch nicht so richtig weiß/wusste wie ich einen Runtime-Loader haben kann, der als Programm vorliegt, ist mir jetzt eine Idee für die Prozesserstellung gekommen, mit der ich vllt sogar fork() anbieten kann, ohne das auf Kernel-Ebene machen zu müssen.

Mein createTask() soll nur einen komplett leeren Task erstellen, nicht mehr und nicht weniger.

Der VFS-Server kann dann über eine private Kernel-API (die soll so geschützt sein, dass nur der VFS-Server sie aufrufen kann) Speicher in einen Prozess "injezieren" (im Endeffekt mappen) können und zwar an Adressen wo er das gerne hätte (soweit es da keine Überschneidungen gibt).

Damit ist es möglich einen Runtime-Loader, der als Programm vorliegt, in den leeren Prozess zu injezieren, einen neuen Thread zu erstellen und dieser Thread führt dann den Runtime-Loader aus, welcher sich die Daten (die ausführbare Datei und die nötigen Libs) vom VFS-Server holt und parst.
Ein weiterer Vorteil ist, dass ich dann auch einfach mehrere Runtime-Loader, für verschiedene Dateiformate, haben kann und vorallem bleiben diese im Prozess gemappt und der Prozess kann dann später noch Libs nachladen (Plug-Ins) und die Symbole auflösen lassen.
Der Runtime-Loader würde dann aus 2 Dateien bestehen, einmal aus dem eigentlichen Runtime-Loader (als Programm oder ne Art Programm, da bin ich mir noch nicht sicher) und einmal aus nem Add-On für den VFS-Server. Das Add-On wäre dafür da, dass der VFS-Server weiß welchen Runtime-Loader er für welche Datei nehmen muss (ne einfache Funktion, die nen Pointer auf z.B. die ersten 8kb von der Datei bekommt und den Header überprüft).
Ganz nebenbei könnte man so auch das Starten jeglicher Dateien, wo Programme für installiert sind, lösen. Sprich jedes Programm bringt für jeden Dateityp den sie unterstützt ein Add-On für den VFS-Server mit (z.B. ein Media-Player ein Add-on für jedes Container-Format oder so). Ist das Overkill? Ich meine man muss ja nicht, man könnte aber, die Funktionalität wäre gegeben.

Genauso kann ich es so ermöglichen das ein fork() über den VFS-Server stattfindet. In dem einfach der schon vorhanden Prozess per COW in den neuen Prozess injeziert wird.

Eine Frage zum fork(), wird da wirklich der komplette Adressraum geclont oder werden z.B. die Stacks weggelassen? Weil letzteres wäre dann schon wieder schwieriger umzusetzen (und wahrscheinlich nicht ohne die Hilfe des Kernels).

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 15. October 2011, 10:34 »
Das große Problem beim fork() ist nicht das Kopieren des Adressraums, sondern dass die beiden Prozesse hinterher gemeinsame Dateideskriptoren haben müssen.

Ob es so clever ist, jedes Programm eine zusätzliche Lib für den VFS-Server installieren zu lassen, weiß ich nicht. Das werden mit der Zeit ja doch ganz schön viele. Bist du sicher, dass du Binärcode brauchst, um Dateiformate zu erkennen und nicht eine einfachere Logik reicht, die fest eingebaut ist und auf eine Datenbank zugreift? Hast du dir z.B. mal angeschaut wie file funktioniert? Das hat meines Wissens auch eine Form von Datenbank und nicht Code für jedes einzelne Format.

Und warum ist ausgerechnet der VFS-Server für das Starten von Prozessen zuständig?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 15. October 2011, 11:01 »
Zitat von: taljeth
Das große Problem beim fork() ist nicht das Kopieren des Adressraums, sondern dass die beiden Prozesse hinterher gemeinsame Dateideskriptoren haben müssen.
Naja, für mich ist eher das Kopieren des Adressraums ein Problem und nicht die Dateidiskriptoren. Wegen den FD´s (und aus einem anderen Grund) wird das ganze ja auch über den VFS-Server gemacht.

Zitat von: taljeth
Ob es so clever ist, jedes Programm eine zusätzliche Lib für den VFS-Server installieren zu lassen, weiß ich nicht.
Jap, ist mir auch schon aufgefallen, zumal es wahrscheinlich daran scheitern würde, dass es nicht reicht das Programm einfach zu "injezieren", weil fast alle Programme noch Libs hätten und dafür bräuchte man wieder den Runtime-Loader.
Sprich die ganze Sache mit dem in einen leeren Adressraum injezieren, bleibt den Runtime-Loadern vorbehalten.

Zitat von: taljeht
Und warum ist ausgerechnet der VFS-Server für das Starten von Prozessen zuständig?
Will man das Unix-Konzept "alles ist eine Datei" nutzen, ist das nun man die Stelle schlechthin dafür (ob ich das nutze, weiß ich noch nicht, wird wohl aber darauf hinauslaufen). Dann kommt noch hinzu, dass der Kernel nix von den Runtime-Loadern weiß, sondern nur der VFS-Server und auch nur diesem ist es erlaubt die leeren Prozesse mit Leben zu füllen.

Ein Problem wäre nur, wenn ich dann schon fork() habe, dann muss ich natürlich auch noch exec() umsetzen und das bereitet mir ein wenig Sorgen. Denn wenn ich dem VFS-Server auch noch die Möglichkeit gebe, den Adressraum eines vorhandenen Prozesse komplett zu löschen, haben alle Add-Ons ganz schön viel Rechte. Allerdings will ich der Einfachheit halber, dass ganze über Datei-Rechte lösen. Sprich man braucht root-Rechte um überhaupt ein Add-On an seinen Platz zu schaffen (die müssen in einem bestimmten Ordner liegen) und ich gehe einfach davon aus, dass das System wenn es installiert wird, sicher ist.
Selbst wenn ich Dateisystem nicht derartige Rechte unterstützt kann ich einfach bestimmte Ordner festlegen wo man für Schreibrechte (Leserechte sind da nicht so wichtig oder?) root-Rechte braucht. Das ganze lässt sich auch wunderbar im VFS-Server umsetzen.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 15. October 2011, 12:17 »
Naja, für mich ist eher das Kopieren des Adressraums ein Problem und nicht die Dateidiskriptoren. Wegen den FD´s (und aus einem anderen Grund) wird das ganze ja auch über den VFS-Server gemacht.
Das heißt, dass du den Dateizeiger im VFS-Server hast und die Programme alle Requests nicht direkt an den Treiber schicken, sondern an den VFS-Server, der die Requests dann entsprechend weiterleitet? Was bedeutet das für die Performance?

Zitat
Dann kommt noch hinzu, dass der Kernel nix von den Runtime-Loadern weiß, sondern nur der VFS-Server und auch nur diesem ist es erlaubt die leeren Prozesse mit Leben zu füllen.
Das müsste ja aber kein VFS-Server sein, sondern ließe sich mit einem anderen Server (sei es ein allgemeiner exec-Server oder ein spezieller ELF-Server) genauso umsetzen. Dass du die FDs nur gescheit hinkriegst, wenn es über den VFS-Server läuft, ist aber nachvollziehbar.

Zitat
Ein Problem wäre nur, wenn ich dann schon fork() habe, dann muss ich natürlich auch noch exec() umsetzen und das bereitet mir ein wenig Sorgen. Denn wenn ich dem VFS-Server auch noch die Möglichkeit gebe, den Adressraum eines vorhandenen Prozesse komplett zu löschen, haben alle Add-Ons ganz schön viel Rechte.
Vielleicht so: Ein Prozess hat ein Flag, das sagt, ob der VFS-Server im Adressraum rumpfuschen darf. Das erste, was der Prozess in _start macht, ist dieses Flag zu löschen und während exec setzt er das Flag halt wieder.

Zitat
Selbst wenn ich Dateisystem nicht derartige Rechte unterstützt kann ich einfach bestimmte Ordner festlegen wo man für Schreibrechte (Leserechte sind da nicht so wichtig oder?) root-Rechte braucht. Das ganze lässt sich auch wunderbar im VFS-Server umsetzen.
Warum willst du für die Systempartition etwas benutzen, das keine Rechte kann?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 15. October 2011, 12:47 »
Zitat von: taljeth
Das heißt, dass du den Dateizeiger im VFS-Server hast und die Programme alle Requests nicht direkt an den Treiber schicken, sondern an den VFS-Server, der die Requests dann entsprechend weiterleitet? Was bedeutet das für die Performance?
Am liebsten wäre es mir wenn die Dateizeiger in der libc wären, aber das wäre ja noch umständlicher mit dem sharen. Das Thema hatten wir ja schon, wie das so ist mit den gemeinsamen Dateizeigern, ob da wirklich gleichzeitig geschrieben und/oder gelesen wird.

Gerade zwecks Performance sehe ich es als besser an das ganze Dateimanagement an einem Ort zu machen. Ich cache sozusagen die Dateien im VFS-Server (immer in vielfachem der Page-Größe bzw. "Cluster"-größe, je nach dem was größer ist).
Vorallem von welchem Treiber redest du? Der Medium-Treiber kennt keine Dateisystemstrukturen, die sind als Add-On im VFS-Server und der holt sich die Daten von den Treibern (wie genau ich das mit den Treibern und Bus-Treibern mache, muss ich mal sehen).

Zitat von: taljeth
Vielleicht so: Ein Prozess hat ein Flag, das sagt, ob der VFS-Server im Adressraum rumpfuschen darf. Das erste, was der Prozess in _start macht, ist dieses Flag zu löschen und während exec setzt er das Flag halt wieder.
Das ist eigentlich ne richtig gute Idee. So kann jeder Prozess selbst entscheiden ob er das zulässt bzw. halt nur exec().

Zitat von: taljeth
Warum willst du für die Systempartition etwas benutzen, das keine Rechte kann?
Ich bin Windows-User und der Einfachheit halber. Ich wollte mich aber eigentlich mal mit extfs2 auseinander setzen und das in meinem Bootloader implementieren (bisher habe ich nur FAT und ISO9660). Linux scheint das doch auch irgendwie hinzubekommen, mit nem Overlay oder so.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 15. October 2011, 13:21 »
Gerade zwecks Performance sehe ich es als besser an das ganze Dateimanagement an einem Ort zu machen. Ich cache sozusagen die Dateien im VFS-Server (immer in vielfachem der Page-Größe bzw. "Cluster"-größe, je nach dem was größer ist).
Das kann und sollte man natürlich machen, hilft aber erst beim zweiten Zugriff oder wenn die Zugriffe so klein sind, dass der VFS-Server sich wesentlich größere Bereich auf einmal in den Cache lädt als das Programm im Moment anfordert.

Zitat
Vorallem von welchem Treiber redest du? Der Medium-Treiber kennt keine Dateisystemstrukturen, die sind als Add-On im VFS-Server und der holt sich die Daten von den Treibern (wie genau ich das mit den Treibern und Bus-Treibern mache, muss ich mal sehen).
Du baust alle Dateisystemtreiber in den VFS-Server ein? Das ist aber kein sehr mikrokerneliger Ansatz.

Zitat von: taljeth
Ich bin Windows-User und der Einfachheit halber. Ich wollte mich aber eigentlich mal mit extfs2 auseinander setzen und das in meinem Bootloader implementieren (bisher habe ich nur FAT und ISO9660). Linux scheint das doch auch irgendwie hinzubekommen, mit nem Overlay oder so.
Windows benutzt NTFS, das ist also kein Argument. ;)

Linux hatte mal UMSDOS, das irgendwie zusätzliche Metadaten auf einem FAT-Dateisystem angelegt hat. War aber wohl immer relativ kaputt und ist soweit ich weiß mittlerweile auch rausgeflogen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 15. October 2011, 14:39 »
Zitat von: taljeth
Du baust alle Dateisystemtreiber in den VFS-Server ein? Das ist aber kein sehr mikrokerneliger Ansatz.
Hmm, darüber lässt sich jetzt streiten ;)

Aus sicht einiger Vertreter habe ich sowieso keinen richtigen MikroKernel da ich ja den Speichermanager im Kernel habe. Allerdings wieso ist dem nicht so? Es läuft nicht im Kernel und so richtig als Treiber würde ich es nicht sehen. Ich habe einen Service (der VFS-Server) und den kann ich per Add-Ons erweitern (so wie Video- und Containerformate bei Mediaplayern).

Wenn ich die Sachen auch noch jeweils in einen extra Prozess lege, dann geht die Performance ja richtig in den Keller, es wird mehr Speicher verbraucht und macht die Sache ja noch komplexer (weil dadurch wieder neue Probleme auftauchen würden).

Zitat von: taljeth
inux hatte mal UMSDOS, das irgendwie zusätzliche Metadaten auf einem FAT-Dateisystem angelegt hat. War aber wohl immer relativ kaputt und ist soweit ich weiß mittlerweile auch rausgeflogen.
Hmm, ich weiß das Linux von nem FAT32 USB-Stick starten kann (obwohl es sein kann das da dann nen Image drauf ist, aber da waren so viel Dateien drauf) und von CD.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 15. October 2011, 14:52 »
Definiere "richtiger Mikrokernel". Nur, weil PMM und VMM im Kernel liegen, ist das noch lange kein Monolith.
Plugin-Technologien sind dagegen ein dynamischer, monolithischer Ansatz. Ein einzelner, riesiger, monolithischer Userspace-Prozess auf einem Mikrokernel führt das Mikrokernelkonzept ohnehin ad absurdum. Und ein Betriebssystem mit einem Mediaplayer zu vergleichen finde ich etwas abwegig. :roll:

Wenn ich die Sachen auch noch jeweils in einen extra Prozess lege, dann geht die Performance ja richtig in den Keller, es wird mehr Speicher verbraucht und macht die Sache ja noch komplexer (weil dadurch wieder neue Probleme auftauchen würden).
Warum baust du dann eigentlich keinen monolithischen Kernel? Da kannst du die Performance eh am feinsten steuern. :-)

UMSDOS war ein Linux-Dateisystem, bei dem die Rechtevergabe usw. in einer speziellen Datei --LINUX-.--- abgelegt waren, so dass FAT wenigstens virtuell um die wichtigsten Fähigkeiten erweitert wurde. Praktisch wurde es fast nie eingesetzt, weil Linux damit anfällig für DOS-Viren wurde und ext2 wesentlich schneller war. Und ja, es ist inzwischen aus dem Kernel rausgeflogen.

Was du meinst ist SYSLINUX. Den hatte ich hier schon öfter empfohlen. Der lädt für Linux einen Kernel und eine initiale Ramdisk von FAT12/16/32 in den Speicher und startet die. Das ist was völlig anderes. Die Initrd von Knoppix beispielsweise mountet dann alle Blockdevices, bis sie die KNOPPIX-Datei gefunden hat (das ist das Knoppix-Root-Dateisystem). Bei CDs wird das gleiche Programm für iso9660 benutzt, ISOLINUX. Der dritte Kollege heißt EXTLINUX und kann ext2/3/4.

Gruß,
Svenska

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 15. October 2011, 15:11 »
Zitat von: svenska
Definiere "richtiger Mikrokernel". Nur, weil PMM und VMM im Kernel liegen, ist das noch lange kein Monolith.
Das sehe ich ja genauso, nur je nach dem wen du fragst ist das dann schonmal kein MikroKernel mehr.

Zitat von: svenska
Plugin-Technologien sind dagegen ein dynamischer, monolithischer Ansatz. Ein einzelner, riesiger, monolithischer Userspace-Prozess auf einem Mikrokernel führt das Mikrokernelkonzept ohnehin ad absurdum.
Naja, was würdest du denn als einzelener monolithischen Userspace-Prozess bezeichnen?

Die Treiber werden wahrscheinlich alle in ihrem eigenem Prozess laufen und die Services sind auch getrennt. Nur sehe ich halt nen Dateisystem nicht als Treiber an.

Zitat von: svenska
Und ein Betriebssystem mit einem Mediaplayer zu vergleichen finde ich etwas abwegig.
Da ging es mir auch nur darum, dass die ganzen unterstützten Media- und Dateiformate dynamisch nachgeladen werden können, aber nicht in einem eigenen Prozess laufen (was ja wohl auch Overkill wäre, aber bestimmt einfacher umzusetzen als die Sache mit den Dateisystemen).

Zitat von: svenska
Warum baust du dann eigentlich keinen monolithischen Kernel? Da kannst du die Performance eh am feinsten steuern.
Was die Performance betrifft hast du da mMn recht. Allerdings mag ich das vieles physisch getrennt von anderen Sachen läuft (z.B. Treiber und die Services). Man kann halt auf nem MikroKernel viele Sachen einfacher dynamisch machen und vorallem leichter austauschen.

Nen schön modularen Monolithen gab es mit BeOS und gibt es wieder mit Haiku. Nur mit dem Linux-Kernel kann ich mich absolut nicht anfreunden (Windows kann ich nix zu sagen, da ich darüber zu wenig weiß).

Auf CDs würde ich gerne die Variante von BeOS nutzen. Da hat man mehrere Tracks auf der CD, der erste Track ist nen normales ISO9660 und die weiteren sind BeFS Images (einmal ein x86 und einmal ein PPC Image).

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 15. October 2011, 15:22 »
Zitat von: svenska
Plugin-Technologien sind dagegen ein dynamischer, monolithischer Ansatz. Ein einzelner, riesiger, monolithischer Userspace-Prozess auf einem Mikrokernel führt das Mikrokernelkonzept ohnehin ad absurdum.
Naja, was würdest du denn als einzelener monolithischen Userspace-Prozess bezeichnen?
Wenn dein VFS-Server sämtliche Dateisysteme beinhaltet (und sei es dynamisch nachladbar als Plugin), dann ist das schon monolithisch. :-)

Da ich das VFS zu den grundlegendsten Funktionalitäten zähle (neben Speicher- und Prozessverwaltung), darf es auch in einem Mikrokernel im Kernel selbst implementiert sein. Wenn alles Dateien sind, dann ist ein Kernel ohne VFS nicht mehr lebensfähig, kann sich also nicht selbst retten.

Die Treiber werden wahrscheinlich alle in ihrem eigenem Prozess laufen und die Services sind auch getrennt. Nur sehe ich halt nen Dateisystem nicht als Treiber an.
Da bin ich anderer Meinung, ist aber ne Definitionsfrage.

Nen schön modularen Monolithen gab es mit BeOS und gibt es wieder mit Haiku. Nur mit dem Linux-Kernel kann ich mich absolut nicht anfreunden (Windows kann ich nix zu sagen, da ich darüber zu wenig weiß).
Warum nicht?

Auf CDs würde ich gerne die Variante von BeOS nutzen. Da hat man mehrere Tracks auf der CD, der erste Track ist nen normales ISO9660 und die weiteren sind BeFS Images (einmal ein x86 und einmal ein PPC Image).
Naja, wer's braucht...

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 15. October 2011, 15:38 »
Zitat von: svenska
Wenn dein VFS-Server sämtliche Dateisysteme beinhaltet (und sei es dynamisch nachladbar als Plugin), dann ist das schon monolithisch.
Naja, dass sehe ich z.B. als KISS an. Wie gesagt, die Dateisysteme auch noch in eigene Prozesse auszulagern würde zu noch mehr Problemen führen.

Zitat von: svenska
Da ich das VFS zu den grundlegendsten Funktionalitäten zähle (neben Speicher- und Prozessverwaltung), darf es auch in einem Mikrokernel im Kernel selbst implementiert sein.
Wow, dann wäre der Haiku-Kernel ja für dich auch noch nen MikroKernel (ich möchte meinen die haben "nur" das VFS im Kernel, bin mir aber nicht sicher). So ist das halt mit den Auslegungen ;)

Zitat von: svenska
Warum nicht?
Zu unflexibel (in meinen Augen) und verwendet Konzepte die ich absolut nicht nachvollziehen kann (ich meine damit, dass ich sie verstehe, aber nicht verstehe warum sie genutzt werden). Mal ganz davon abgesehen das ich ihn inzwischen auch für bloated halte und wie man den nicht konfigurieren kann, damit er ja auch auf allen Architekturen läuft. Dann lieber vieles physisch voneinander trennen und den Kernel so klein wie möglich halten (da würde ich dann sogar nix gegen ein VFS im Kernel haben, ist ja wie du sagtest ein muss für das OS).

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 15. October 2011, 20:45 »
Hallo,


@FlashBurn:
Auch wenn ich grundsätzlich nix vom injizieren von Speicher halte so empfinde ich die von Dir ganz oben beschriebene Vorgehensweise durchaus als machbar, aber es gibt einige Nachteile: die enormen Rechte der Module Deines Loaders hast Du ja selber erkannt und der hohe und redundante Speicherverbrauch wurde auch schon erwähnt. Warum nicht den Executable-Loader in den Kernel packen? Wenn Du unbedingt AddOns haben willst dann lass die als Vorverarbeitung im User-Space laufen und erst das fertige Executable (das dann im simplen Format für den Kernel vorliegt) an den Kernel weitergeben. Vor allem wüste ich gerne mal was Du mit Modulen meinst. Darf ich mir das so wie DLL's unter Windows vorstellen die dann erst wenn sie wirklich benötigt werden per LoadDLL() geladen werden? Was ich mich da immer frage: was ist mit den Call-Befehlen im normalen Code der auf diese Funktionen zeigt? Wenn die noch nicht reloziert sind dann zeigen die ja ins Nirwana so das wenn das Programm so einen Call doch mal ausführt das es dann (kontrolliert) abstürzt. Normale Librarys werden zum Start des Programms eingebunden so das die durchaus mit einer Vorverarbeitung im User-Space zu erledigen wären.

Bei fork() muss übrigens auch der Stack komplett mit kopiert werden, und auch alle anderen Speicherbereiche (auch solche die erst zur Laufzeit angelegt wurden) ich glaube sogar Shared-Memory (bin mir da aber nicht sicher). Es sollte auf jeden Fall noch jeder Pointer funktionieren. Dazu kommen dann eben noch die ganzen File-Desciptoren und ich denke es gibt noch andere Sachen aber das sollte ein genauer Blick in die POSIX-Spezifikation klären können. Ich schätze so ganz ohne aktive Hilfe des Kernels lässt sich fork() nicht ohne Würgereiz (und dem Lieblings-K-attribut von taljeth, SCNR) umsetzen. Das einzigste was da noch bleiben würde ist die Variante von cygwin aber gerade die ließe sich ja mit Deiner ursprünglichen Idee mit dem Executable-Loader tatsächlich umsetzen.

Die Dateisysteme mit in den VFS-Prozess zu integrieren empfinde ich auch als etwas zu monolithisch, da hätte man ja wieder einen fetten Single-Point-of-Failure.
In meiner Fantasie ist der VFS vor allem eine Art Switch an den sich alle Block-Devices, File-System-Treiber (ohne eine konkrete Instanz) und auch alle fertigen Dateisysteme (z.B. NFS-Clients) anmelden können. Der VFS zerlegt dann z.B. die Block-Devices (falls diese partitioniert sind) und lässt alle File-System-Treiber prüfen (anhand der ersten 8 kB o.ä.) ob sie was damit anfangen können, falls ja weißt der VFS den File-System-Treiber an eine neue Instanz (innerhalb seines Prozesses) zu erstellen und teilt dabei mit auf welchen Block-Device in welcher Partition das liegt (damit der Datei-System-Treiber dann direkt mit dem entsprechenden Block-Device-Treiber kommunizieren kann). Das einzigste was mir dabei noch Kopfzerbrechen bereitet ist das Verwalten der Mount-Points, das VFS kann dazu zwar auf fstab für die bekannten Partitionen zurückgreifen aber für alles andere wird eine gescheite Automatik benötigt (wovon ich aber nicht so arg viel halte) oder der User muss das manuell machen (ist auch nicht toll).
Das Caching würde ich auch komplett im VFS machen und nicht den einzelnen File-Systemen überlassen (dann könnte der Kernel auch an VFS eine IPC-Message schicken das der Speicher knapp wird und VFS kann dann mal ein wenig aufräumen). Ich würde sogar soweit gehen das der VFS selbst das Anlegen von Dateien cached so das die z.B. erst dann an den eigentlichen Datei-System-Treiber weitergegeben werden (mit der endgültigen Größe usw.) wenn der User-Prozess die Datei längst geschlossen hat (falls er nicht vorher flushall() aufgerufen hat). Der VFS sollte auch beim Öffnen von Verzeichnissen diese immer komplett vom Datei-System-Treiber abfragen (mitsamt allen Meta-Informationen) und dann immer auf dieser internen Darstellung arbeiten. Auf diese Art besteht im Datei-System-Treiber (oder gar im Block-Device-Treiber) auch nicht die Notwendigkeit irgendetwas zu cachen.

Dass das VFS in den Micro-Kernel gehört würde ich persönlich dann doch eher verneinen, mein Micro-Kernel soll nicht mal wissen das es überhaupt Dateien gibt (wozu auch? mir fällt da absolut kein Grund ein), aber ich schätze mit dieser Meinung bin ich hier wohl eindeutig in der Unterzahl.


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

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #12 am: 15. October 2011, 20:59 »
Dass das VFS in den Micro-Kernel gehört würde ich persönlich dann doch eher verneinen, mein Micro-Kernel soll nicht mal wissen das es überhaupt Dateien gibt (wozu auch? mir fällt da absolut kein Grund ein), aber ich schätze mit dieser Meinung bin ich hier wohl eindeutig in der Unterzahl.

Ich wollte nur rasch hierzu was sagen: Und zwar ist ja IPC eine zentrale Aufgabe des Mikrokernels. Somit finde ich das VFS im Kernel bei einem OS, das das VFS als primäre IPC-Methode benutzt nicht soo verkehrt.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 15. October 2011, 21:08 »
Zitat von: erik
und der hohe und redundante Speicherverbrauch wurde auch schon erwähnt.
Hier stehe ich irgendwie aufm Schlauch, welcher hohe und redundante Speicherverbrauch?

Zitat von: erik
Warum nicht den Executable-Loader in den Kernel packen? Wenn Du unbedingt AddOns haben willst dann lass die als Vorverarbeitung im User-Space laufen und erst das fertige Executable (das dann im simplen Format für den Kernel vorliegt) an den Kernel weitergeben.
Naja, keine halben Sachen, sprich entweder ganz oder gar nicht. Soll heißen, mit dem einfachen Format wäre es ja nicht getan, um zur Laufzeit Libs nachladen zu können, müsste der Kernel entweder die Formate kennen oder ich brauche was im UserSpace. Dann sagst du, dass das halt der UserSpace-Teil machen soll, aber wo sind dann die Symboltabellen?
Deswegen soll der Kernel gar nix davon wissen und der entsprechende Runtime-Loader ist immer und dauerhaft im Prozess gemappt (obwohl man da optmieren könnte und jeder Prozess könnte festlegen ob das wirklich sein muss). Damit ginge zwar auch "nur" das Libs nur im selben Format nachgeladen werden, wie das Hauptprogramm, aber ich denke mit der Einschränkung kann ich leben ;)

Zitat von: erik
Vor allem wüste ich gerne mal was Du mit Modulen meinst.
Ich habe alle meine Beiträge nochmal gelesen und da tauchen keine Module, aber sehr wohl Add-Ons auf. Das sollen ne Art Plug-Ins sein, die erst zur Laufzeit hinzugefügt werden.

Zitat von: erik
Bei fork() muss übrigens auch der Stack komplett mit kopiert werden, und auch alle anderen Speicherbereiche (auch solche die erst zur Laufzeit angelegt wurden) ich glaube sogar Shared-Memory (bin mir da aber nicht sicher). Es sollte auf jeden Fall noch jeder Pointer funktionieren.
Das macht die Sache doch einfacher, darum ging es mir eigentlich nur.

Zitat von: erik
Die Dateisysteme mit in den VFS-Prozess zu integrieren empfinde ich auch als etwas zu monolithisch, da hätte man ja wieder einen fetten Single-Point-of-Failure.
Das muss ich bei der konkreten Implementierung sehen. Im Moment gefällt mir das irgendwie nicht, dass jedes Dateisystem seinen eigenen Prozess bekommt. Das kostet wahrscheinlich richtig Performance und verursacht bestimmt auch neue Probleme.

Wenn ich natürlich sehe, dass die Dateisysteme nur an wenigen Bestimmten Stellen so aufgerufen werden, dass ich sie auch auslagern könnte, kann ich darüber ja nochmal nachdenken.

Zitat von: FreakyPenguin
Ich wollte nur rasch hierzu was sagen: Und zwar ist ja IPC eine zentrale Aufgabe des Mikrokernels. Somit finde ich das VFS im Kernel bei einem OS, das das VFS als primäre IPC-Methode benutzt nicht soo verkehrt.
Wie soll ich mir das vorstellen, das VFS als primäre IPC-Methode? Pipes und Dateien?
« Letzte Änderung: 15. October 2011, 21:51 von FlashBurn »

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 15. October 2011, 21:42 »
Für jedes Dateisystem einen eigenen Prozess zu benutzen ist nicht unbedingt langsam. Die meisten Dateisysteme arbeiten ohnehin mit realen Devices, deren Latenz wesentlich größer sein dürfte als der Overhead eines Kontextswitches (allein schon, weil es durch das PCI-Subsystem muss - und damit durch mindestens zwei weitere Kontextwechsel).

Das VFS als IPC-Methode ist ein Grund, an den ich nicht gedacht hatte. Mit virtuellen Dateisystemen (/proc, /sys) ist das durchaus möglich. Allerdings hätte ich IPC noch neben VFS, VMM und PMM (und evtl. vergessenen Dingen) gesehen. Im Hinterkopf habe ich dabei aber immer unixoide Systeme, da ist für ein fork() schon einiges an Hintergrundwissen über Dateien notwendig.

Gruß,
Svenska

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 15. October 2011, 21:51 »
Hallo,


Und zwar ist ja IPC eine zentrale Aufgabe des Mikrokernels. Somit finde ich das VFS im Kernel bei einem OS, das das VFS als primäre IPC-Methode benutzt nicht soo verkehrt.
Okay, diesen Einwand lass ich natürlich gelten. Obwohl ich schon der Meinung bin das ein anständiger Micro-Kernel sich bemüht ein effizientes IPC/RPC anzubieten und da sind z.B. Pipes im Dateisystem nicht so wirklich die optimale Wahl.


Hier stehe ich irgendwie aufm Schlauch, welcher hohe und redundante Speicherverbrauch?
Ich dachte Dein Loader ist dann in jedem Prozess mit enthalten damit er später eben AddOns nachladen kann usw., aber wenn der extern bleiben soll is auch gut, wobei das dann einige Dinge wohl ziemlich umständlich machen würde.

Naja, keine halben Sachen, sprich entweder ganz oder gar nicht.
Hm, okay.

aber wo sind dann die Symboltabellen?
Na die liegen noch im User-Space und zur Not können die auch noch mal aus dem Executable nachgeladen werden.

Ich habe alle meine Beiträge nochmal gelesen und da tauchen keine Module, aber sehr wohl Add-Ons auf. Das sollen ne Art Plug-Ins sein, die erst zur Laufzeit hinzugefügt werden.
Sorry, da hab ich mich wohl verlesen. Trotzdem wüste ich gerne wie das überhaupt funktionieren soll. Werden dann Reste in der Executable nachträglich reloziert?

Das kostet wahrscheinlich richtig Performance
Das hängt doch nur davon ab ob Du ein IPC mit geringem Overhead (wie z.B. Zero-Copy) hinbekommst. ;)

und verursacht bestimmt auch neue Probleme.
Welche denn? Solange Du das API zwischen VFS und den Dateisystemen klar strukturierst sollte es völlig egal sein ob da IPC dazwischen ist oder nicht.


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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 15. October 2011, 22:07 »
Zitat von: erik
Ich dachte Dein Loader ist dann in jedem Prozess mit enthalten damit er später eben AddOns nachladen kann usw., aber wenn der extern bleiben soll is auch gut, wobei das dann einige Dinge wohl ziemlich umständlich machen würde.
Das meintest du, ja dann hast du recht, aber bei Linux ist es doch genauso (dort ist es irgendeine ld.so oder so). Der Runtime-Loader liegt als ein fertiges Programm vor, dass nur noch gemappt werden muss (und damit in jedem Prozess die selben Pages nutzt).
Benutzt der Prozess keine Plug-Ins oder ähnliches zur Laufzeit, kann man diesen ja wieder unmappen bzw. würde es wahrscheinlich besser sein, einfach nach bestimmten Symbolen zu gucken (das wäre z.B. dlopen() und solche Sachen) und ihn dann nicht zu unmappen, ansonsten aber schon.

Zitat von: erik
Trotzdem wüste ich gerne wie das überhaupt funktionieren soll. Werden dann Reste in der Executable nachträglich reloziert?
Plug-Ins zur Laufzeit funktionieren so, dass du dir ne Liste von denen merkst und die ein ganz bestimmtes API implementieren. Im Endeffekt ruft das eigentliche Programm die Funktionen nur über eine Struktur mit Funktionspointern (siehe VFS bei Linux und bestimmt auch allen anderen OS´s) auf, aber im Plug-In werden Symbole reloziert, nicht aber im eigentlichen Programm.

Zitat von: erik
Das hängt doch nur davon ab ob Du ein IPC mit geringem Overhead (wie z.B. Zero-Copy) hinbekommst.
Wohl eher nicht bzw. hängt davon ab wie detailiert du es betrachtest. Das Senden und Empfangen von Daten sollte mehr oder weniger per Zero-Copy gehen, die eigentliche Kommunikation (welche Operation und sowas) wird durch kopieren passieren und die Implementierung in der libc wird definitiv nur über kopieren zu lösen sein (geht auch gar nicht anders ohne Segmente, irgendwo muss immer kopiert werden).

Zitat von: erik
Welche denn? Solange Du das API zwischen VFS und den Dateisystemen klar strukturierst sollte es völlig egal sein ob da IPC dazwischen ist oder nicht.
Wo würden dann die FD´s sein? Im VFS oder im Dateisystem-Programm?

Zitat von: svenska
Für jedes Dateisystem einen eigenen Prozess zu benutzen ist nicht unbedingt langsam. Die meisten Dateisysteme arbeiten ohnehin mit realen Devices, deren Latenz wesentlich größer sein dürfte als der Overhead eines Kontextswitches (allein schon, weil es durch das PCI-Subsystem muss - und damit durch mindestens zwei weitere Kontextwechsel).
Overhead ist da, aber er wäre so geringer.

Ich versuche mir das gerade vorzustellen. Das VFS müsste auf jeden Fall immer alle Pfade bis zu einem Mount-Point zwischenspeichern. Auch wäre es bestimmt nicht schlecht wenn Directories irgendwie gecacht werden.

Ansonsten wären das halt anstatt Funktionsaufrufen IPC-Requests. Möglich wäre es, nur die Frage wofür man optimiert? Wenn ich da an SSDs denke, könnte sich der Overhead bemerkbar machen oder? Bei normalen HDDs nicht.
Aber was wäre durch den Overhead gewonnen? Zumal es halt wesentlich mehr Speicher verschlingen würde und den Systemstart nicht einfacher macht. Ich wüsste jetzt auch nicht wie komplex solche "Programme" dann wären, sprich was sie an Libs benötigen würden.
Da muss ich nochmal ne Nacht drüber schlafen, aber ihr könnt ja versuchen es mir schmackhaft zu machen ;)

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 16. October 2011, 11:57 »
Hallo,


zu Deinem Loader fällt mir noch ein das Du es lösen musst den Speicher mit den richtigen Rechten (für den neuen Prozess) zu injizieren. Also z.B. Code sollte als Executable-Only gemappt sein und ASLR solltest Du auch (zumindest konzeptionell) vorsehen.

Plug-Ins zur Laufzeit funktionieren so, dass du dir ne Liste von denen merkst und die ein ganz bestimmtes API implementieren.
Hä? Soll die Liste ein API implementieren?

Im Endeffekt ruft das eigentliche Programm die Funktionen nur über eine Struktur mit Funktionspointern (siehe VFS bei Linux und bestimmt auch allen anderen OS´s) auf, aber im Plug-In werden Symbole reloziert, nicht aber im eigentlichen Programm.
Diese Strucktur-Member dann später (zur Laufzeit) auf den richtigen Code zeigen zu lassen ist auch relozieren. Auf was zeigen diese Funktions-Pointer vorher? Nebst dessen das solche Strukturen besser in rodata liegen damit das eigentliche Programm da nicht aus versehen was doofes reinschreibt, damit sollte Dein Loader umgehen können.

Das Senden und Empfangen von Daten sollte mehr oder weniger per Zero-Copy gehen
Das meinte ich auch, die Metadaten sind doch nur ein paar Bytes so das dort Kopieren immer billiger als Mappen sein sollte.

die Implementierung in der libc wird definitiv nur über kopieren zu lösen sein (geht auch gar nicht anders ohne Segmente, irgendwo muss immer kopiert werden).
Hm, ich wollte eher im VFS kopieren, dort muss man das doch eh tun wenn man anständigen Cache haben will. In der libc würde ich nur dann cachen wenn z.B. eine Datei per readln eingelesen wird aber wenn dort read(file,buffer,1000000) steht dann soll das VFS lieber direkt von seinem Cache in den eigentlich User-Buffer kopieren. Es ist IMHO auch unwahrscheinlich das ein Programm die selben Bytes aus einer Datei mehrfach hintereinander einließt so das es eher darum geht dass das VFS nicht für zu arg kleine Häppchen in Anspruch genommen wird was also eher für ein dezentes Read-Ahead und Write-Combining in der libc spricht (und für richtiges Datei-Caching ist die libc auf jeden Fall der falsche Ort).

Wo würden dann die FD´s sein? Im VFS oder im Dateisystem-Programm?
Auf jeden Fall nicht im Datei-System-Treiber, ich würde dort nicht mal irgendeine Art von Datei-Handle o.ä. haben wollen, eher würde ich dem VFS immer 2 oder 3 uint64_t Werte vom Datei-System-Treiber mitgeben die dann vom VFS wieder an den Datei-System-Treiber übergeben werden müssen damit diese z.B. zum schnelleren Finden der Datei benutzt werden können (bei FAT wäre das z.B. der Start-Cluster des Verzeichnisses und das Offset mit dem Verzeichniseintrag innerhalb des Verzeichnisses wenn es um die Metadaten geht und der Start-Clusster der eigentlichen Datei wenn es um die Datei selber geht, bei ext wohl eher eine INode-Nummer). Es ist auf jeden Fall Speicher-Effizienter wenn das Cache-Management nur einmal gemacht wird und da bietet sich das VFS geradezu an.

Wenn ich da an SSDs denke, könnte sich der Overhead bemerkbar machen oder?
Dann denk mal an eine PCIe-RAM-Disk (also ein HDD-Controller auf einer PCIe-Karte an dem direkt 4 oder mehr GB normaler DRAM hängen), damit kann man selbst bei zufälligem Lesen und Schreiben (es muss ja kein Wear-Leveling durchgeführt werden) von einzelnen Sektoren Commit-Zeiten von unter 1 µs erreichen. Da ist die SW-Schichtung im OS immer der Bremsklotz. Aber sowas ist eben auch für keinen von uns der normale Einsatzzweck, ich denke das 3 SW-Schichten im OS (VFS / Datei-System-Treiber / Block-Device-Treiber) ganz okay sind, bei normalen HDDs dürfte das nichtmal messbar sein.

Ich wüsste jetzt auch nicht wie komplex solche "Programme" dann wären, sprich was sie an Libs benötigen würden.
Ich vermute mal das so ein Datei-System-Treiber als eigenständiger Prozess fast gar nichts an libs braucht, außer malloc/free, nen printf für Fehlermeldungen und etwas Code zum umrechnen von Zeitwerten (Datei-System-Format <> UTC) fällt mir nicht viel ein.


noch etwas OT (ich finde jetzt auf die Schnelle nicht mehr den richtigen Thread):
Du hast doch mal gefragt ob man von einer virtuellen Adresse auf das zugehörige Objekt schließen können muss also ob man im VMM im Kernel auch die belegten Blöcke verwalten sollte: ich denke ja, weil spätestens wenn Du doch mal swappen willst must Du in der Lage sein zu wissen was Du gerade auslagerst wenn Dir die Page-Ersetzungsstrategie eine Page vorschlägt.


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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 16. October 2011, 12:14 »
Zitat von: erik
zu Deinem Loader fällt mir noch ein das Du es lösen musst den Speicher mit den richtigen Rechten (für den neuen Prozess) zu injizieren. Also z.B. Code sollte als Executable-Only gemappt sein und ASLR solltest Du auch (zumindest konzeptionell) vorsehen.
Das wäre alles kein Problem, da man sowas ja beim Mappen mit angeben kann. Auch ASLR kann wunderschön im Loader implementiert werden ohne das der Kernel geändert werden muss oder etwas darüber wissen muss.

Was Plug-Ins betrifft, ist kein Plug-In geladen ist auch kein Element in der Liste. Die Listeneinträge werden erst erstellt wenn ein Plug-In geladen ist und sehen z.B. so aus:
struct PlugInAPI {
 uint32 (*open)(const char* name);
 uint32 (*close)(uint32 handle);
};
Und jedes Plug-In muss mindestens die Symbole haben, die man für diese Struktur benötigt oder am besten noch, die Struktur selbst ist im Plug-In gespeichert und kann durch einen Funktionsaufruf geholt werden.

Zitat von: erik
Du hast doch mal gefragt ob man von einer virtuellen Adresse auf das zugehörige Objekt schließen können muss also ob man im VMM im Kernel auch die belegten Blöcke verwalten sollte: ich denke ja, weil spätestens wenn Du doch mal swappen willst must Du in der Lage sein zu wissen was Du gerade auslagerst wenn Dir die Page-Ersetzungsstrategie eine Page vorschlägt.
Ich kann dir gerade nicht ganz folgen was du genau meinst, aber ich habe ne art PageStruc Tabelle, wo für jede physisches Page gespeichert ist, wie oft sie gemappt ist und noch zusätzlich ein 4byte Wert gespeichert werden kann (wird im Mom nur vom SlabAllocator genutzt um auf die Slab-Struktur zu kommen).

Ansonsten hätte ich gesagt, kann man beim Speicheranfordern/Mappen sagen, ob der Speicher geswappt werden darf oder nicht.

Edit::

Was dynamisches Laden zur Laufzeit betrifft: http://en.wikipedia.org/wiki/Dynamic_loading
« Letzte Änderung: 16. October 2011, 12:16 von FlashBurn »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 16. October 2011, 13:18 »
FlashBurn, eine Frage, die sich mir bei deinem ursprünglichen Modell stellt, ist, ob man in deinem OS auf Sachen wie Block und Character Devices mit den normalen Dateisystemoperationen zugreifen können soll. Habe ich also irgendwie sowas wie ein /dev/hda? Wenn ja, dann hast du schon Treiber vorgesehen, die außerhalb des VFS liegen und an die Requests einfach durchgereicht werden müssen. Warum nicht also konsistent das gleiche mit Dateisystemen machen?

Aber Erik hat auch noch ein schönes anderes Stichwort geliefert, nämlich NFS. Dort kann du kein Block-Backend abtrennen. Willst du also das ganze Netzwerkzeug in den VFS-Server einbauen? Wenn ich dein OS hacken sollte, wüsste ich dann jedenfalls schon, wo ich ansetzen würde - den VFS-Server unter seiner Kontrolle zu haben klingt nach einem guten Anfang. ;)

Okay, diesen Einwand lass ich natürlich gelten. Obwohl ich schon der Meinung bin das ein anständiger Micro-Kernel sich bemüht ein effizientes IPC/RPC anzubieten und da sind z.B. Pipes im Dateisystem nicht so wirklich die optimale Wahl.
Weil?

Was du in der Regel für IPC brauchst sind einige wenige Metadaten und je nach Request möglicherweise noch ein großer Haufen Nutzdaten. Die Metadaten in eine Pipe und die Nutzdaten eventuell über einen anderen Mechanismus wie Shared Memory klingt für mich eigentlich sehr sinnvoll (und deswegen ist das ja auch die Richtung, in die wir mit LIOv2 gehen).
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

 

Einloggen