Autor Thema: Neuen Prozess laden/starten (Mikrokernel)  (Gelesen 22694 mal)

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #40 am: 06. October 2010, 08:52 »
Ich habe noch nicht genau verstanden, was dir am stdio-Beispiel nicht zusagt. Es ist kein Spezialfall und vermutlich der Haupteinsatzzweck der Deskriptorvererbung. Ein viel schöneres und praktischeres Beispiel kannst du doch gar nicht mehr bekommen?
Mir gefällt nicht das es ein Spezialfall ist, es geht dabei um das weitervererben eines Endes einer Pipe also um das weitervererben eines Input-Streams oder Output-Streams. Streams sind was völlig anderes als Dateien (ich denke für Streams hab ich ein funktionsfähiges Konzept in meine ToDo-Liste geschrieben). Wenn Descriptorvererbung nur für Streams/Pipes gemacht wird (was zweifelsohne der Haupteinsatzzweck ist) dann muss ich erst gar keine Vererbung von Dateien implementieren. Es geht mir darum ob es für diesen Nebeneinsatzzweck (vererben von Dateidescriptoren) auch reale Beispiele gibt an denen man sich orientieren könnte wie das ungefähr umzusetzen ist.
Man kann unter Unix aber auch in/aus einer Datei pipen - va. kann man beim beim Pipen in eine Datei das geschriebene am Ende anhängen lassen (oder auch nicht), was natürlich voraussetzt, dass der Dateizeiger auch mitvererbt wird. Aber man könnte das eventuell durch eine zusätzliche Pipe an die Shell, die dann das eigentliche Schreiben in die Datei übernimmt, lösen, aber das ist zum einen weniger performant, zum anderen natürlich fricklig zu implementieren. Auf den ersten Blick sieht es auch so aus, als ob man das dann nicht (ohne Signale) in einem POSIX-Layer verbergen kann.
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 #41 am: 06. October 2010, 10:26 »
Hallo,


Man kann unter Unix aber auch in/aus einer Datei pipen
Genau das (das letzte Wort) macht den Unterschied zur echten Datei-Vererbung. Die Shell gibt an ihr Kind immer Streams für sdtin/stdout/stderr weiter, ob das die Streams sind die die Shell selber bekommen (geerbt) hat oder ob das Streams von einem Mechanismus sind der Dateien pipen kann ist völlig egal. Dieser Mechanismus muss innerhalb der Shell implementiert werden aber den stelle ich mir recht einfach vor (bei einem Output-Stream wird eben jedes write in ein fappend umgesetzt und bei einem Input-Stream wird jedes read in ein fread umgesetzt).

aber das ist zum einen weniger performant, zum anderen natürlich fricklig zu implementieren.
Wieso sollte das weniger performant als das schreiben in eine geerbte Pipe sein? Die Shell muss die gestreamten Daten weitergeben, entweder an den eigenen Parent oder ans VFS, ich sehe da keinen relevanten Unterschied. (bei stdin das ganze natürlich andersrum)

Auf den ersten Blick sieht es auch so aus, als ob man das dann nicht (ohne Signale) in einem POSIX-Layer verbergen kann.
Wo siehst Du da das Problem? Das weiterleiten von Streams wollte ich über IPC-basiertes RPC machen.


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

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #42 am: 06. October 2010, 13:41 »
aber das ist zum einen weniger performant, zum anderen natürlich fricklig zu implementieren.
Wieso sollte das weniger performant als das schreiben in eine geerbte Pipe sein? Die Shell muss die gestreamten Daten weitergeben, entweder an den eigenen Parent oder ans VFS, ich sehe da keinen relevanten Unterschied. (bei stdin das ganze natürlich andersrum)
Unter Unix geht das aber direkt in die Datei und nicht erst durch eine Pipe an die Shell (denke ich, aber da lass ich mich gerne eines besseren belehren), deswegen weniger performant und deswegen denke ich auch, dass das fricklig ist, da du über eine Pipe emulieren musst, was POSIX direkt machen könnte. Gut, wenn du deine eigene Shell schreibst ist das sowieso wurst, aber wenn du eine portierst nehme ich mal an, dass die davon ausgeht, dass sie einfach eine Datei als stdout/stdin "vererben" kann und die Sache hat sich für diese Shell gegessen (d.h. sie wird nicht versuchen eine Pipe zu vererben und dann da manuell die Datei rein/rauszupipen). Das müsstest du also im POSIX-Layer für die Shell übernehmen. Was aber bescheiden wird, weil es asynchron zur eigentlichen Befehlssequenz der Shell passieren muss.
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 #43 am: 06. October 2010, 14:58 »
Hallo,


Unter Unix geht das aber direkt in die Datei und nicht erst durch eine Pipe an die Shell
Bei einem Monolithen und der Prozesserstellung mit fork ist das sicher der beste Weg aber bei einem Micro-Kernel und ohne fork empfinde ich das vererben von Streams besser (das vererben richtiger Dateien erscheint mir irgendwie viel zu aufwendig). Wenn man kein durchreichen der Daten will dann benötigt man eine zentrale Stelle im System, da bietet sich zwar der VFS an aber IMHO ist das nicht seine Aufgabe, man würde ihm eigentlich fremde Arbeit aufbürden nur weil man versucht alles auf Dateien abzubilden.

aber wenn du eine portierst nehme ich mal an, dass die davon ausgeht, dass sie einfach eine Datei als stdout/stdin "vererben" kann und die Sache hat sich für diese Shell gegessen (d.h. sie wird nicht versuchen eine Pipe zu vererben und dann da manuell die Datei rein/rauszupipen). Das müsstest du also im POSIX-Layer für die Shell übernehmen. Was aber bescheiden wird, weil es asynchron zur eigentlichen Befehlssequenz der Shell passieren muss.
Ich wollte eigentlich schon versuchen eine Shell zu portieren und die soll für stdin/stdout/stderr immer Strems vererben, das bedeutet ich muss diesen Code eh anfassen (obwohl ich mir vorstellen könnte das wenn die Shell nur mit FILE* arbeitet das gar nicht so viel ist). Das die Shell damit als IPC-Service gegenüber ihren Kindern auftritt ist mir klar, das muss dann eben in speziellen Code gemacht werden. Ganz ohne Portierungsaufwand komme ich auf jeden Fall nicht zum Ziel.


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 #44 am: 06. October 2010, 17:14 »
Waren Stdout/Stderr/Stdin nicht die ersten 3 Filehandles eines Prozesses?

Ich habe mir das dann so vorgestellt, das man einfach so als wenn man in die Datei schreiben würde den write-Aufruf macht und das VFS dann die Daten an meinen App-Server per Pipe weitersendet. So wird zwar unnötig kopiert aber das sollte mir einige Probleme vom Hals halten.
So kann ich auch ganz einfach das Vererben lösen.

Ich muss allerdings erik zustimmen, dass das eigentlich nicht die Aufgabe des VFS ist.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #45 am: 06. October 2010, 21:16 »
Ich wollte eigentlich schon versuchen eine Shell zu portieren und die soll für stdin/stdout/stderr immer Strems vererben, das bedeutet ich muss diesen Code eh anfassen (obwohl ich mir vorstellen könnte das wenn die Shell nur mit FILE* arbeitet das gar nicht so viel ist).
Welche Shell kennst du denn, die nur FILE* benutzt? ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #46 am: 06. October 2010, 21:17 »
Hallo,

Dass das üblicherweise zwischen Applikation und Kernel kommt liegt doch daran das übliche OSe Monolithen sind, bei einem Micro-Kernel-OS hat der Kernel überhaupt gar nichts damit zu tun da trifft das eher die Personality und die libc muss das passend verbergen so das auch dieses Konglomerat von Services wie ein OS aussieht.
Eben. Dem Anwendungsprogramm ist es völlig egal, mit wem es da eigentlich redet, im Endeffekt ist es "der Kernel". Die Abstraktion, mit wem da eigentlich geredet wird, verbirgst du in der libc. Mein Gedanke ist, wenn du die Schnittstelle von der libc im Kernel zumindest ansatzweise auch hast, bleibt diese Abstraktion sehr dünn.

Das macht die libc einfacher. Denn meine Frage ist: Wenn ich schon eine gut funktionierende API im Userspace habe - warum dann nicht die gleichen Konzepte auch im Kernel verwenden?

Prinzipiell musst du ja "nur" die IPC-Kommunikation über Sockets machen, die du miteinander verbinden kannst. Das heißt, dein Prozess redet via libc mit dem VFS, das VFS kriegt mit, dass der Plattentreiber gemeint ist und verbindet diese Deskriptoren quasi-miteinander, so dass die Kommunikation nicht mehr über das VFS läuft. Wenn der Plattentreiber nicht mehr kann oder will (z.B. nicht im HD-Treiber implementierte Funktion wie "cd"), gibt er den Deskriptor zurück an das VFS, was dann damit machen kann, was es will.

Kann dein Kernel das, ist die libc einfacher. Andersrum gilt entsprechendes.

Ich hab XML mal für eine ganz simple Konfigurationsdatei benutzt und ich bin mir sicher das dort kaum Fehler drin waren. Der Quell-Code fürs speichern und wieder einlesen war kaum über 20 kBytes und basierte im wesentlichen auf fprintf und strcmp (beim einlesen hab ich erst die komplette Datei in einen Puffer geladen und diesen dann durchgearbeitet).
Dann hast du gerade kein XML verwendet, sondern eine XML-ähnliche, eigene Markup-Language. Guck mal in die XML-Spec, was du für XML alles können musst!

Wenn man kein durchreichen der Daten will dann benötigt man eine zentrale Stelle im System, da bietet sich zwar der VFS an aber IMHO ist das nicht seine Aufgabe, man würde ihm eigentlich fremde Arbeit aufbürden nur weil man versucht alles auf Dateien abzubilden.
Richtig. Wenn du aber dem VFS die Möglichkeit gibst, allgemeingültig "alles" auf Dateien abzubilden, dann sparst du dir in anderen Layern sehr viel Arbeit, wenn du dieses Konzept gründlich umsetzt. Und dann ist es Kernaufgabe des VFS.

Waren Stdout/Stderr/Stdin nicht die ersten 3 Filehandles eines Prozesses?
Prinzipiell ja.

Ich habe mir das dann so vorgestellt, das man einfach so als wenn man in die Datei schreiben würde den write-Aufruf macht und das VFS dann die Daten an meinen App-Server per Pipe weitersendet. So wird zwar unnötig kopiert aber das sollte mir einige Probleme vom Hals halten.
So kann ich auch ganz einfach das Vererben lösen.
Siehe oben. Wenn es möglich ist, solltest du einen Mechanismus implementieren können, damit du dir das durchreichen sparst. Wie man das konkret lösen kann, weiß ich nicht und vermute, dass es stark vom IPC-Konzept abhängt.[/quote]

Ich muss allerdings erik zustimmen, dass das eigentlich nicht die Aufgabe des VFS ist.
Nun, wenn du alles auf Dateien abbildest, dann schon... dann ist es sogar die exakte Aufgabe des VFS (darum ist es ja "virtual"...)

Grüße.
Svenska

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #47 am: 07. October 2010, 10:00 »
Hallo,


Welche Shell kennst du denn, die nur FILE* benutzt? ;)
Keine, ich hab noch nie in den Quell-Code einer Shell reingesehen. Ich hatte eben die Vermutung/Hoffnung das man das so macht, es wäre aus meiner naiven Sicht logisch. ;)


Dem Anwendungsprogramm ist es völlig egal, mit wem es da eigentlich redet, im Endeffekt ist es "der Kernel". Die Abstraktion, mit wem da eigentlich geredet wird, verbirgst du in der libc.
2x ACK

Mein Gedanke ist, wenn du die Schnittstelle von der libc im Kernel zumindest ansatzweise auch hast, bleibt diese Abstraktion sehr dünn.
Die Abstraktion in der libc bleibt IMHO so auch recht dünn, die Standard-Funktionen enthalten im wesentlichen ein switch(descriptor->type) und führen dann spezifische Funktionsaufrufe durch (das ist IMHO ziemlich dünn). Klar würde man im VFS nicht viel anderes implementieren aber dort hat man das Problem die Daten "weiterleiten" zu müssen (auch wenn das bei mir ohne kopieren geht so möchte ich das trotzdem vermeiden) wogegen die libc gleich direkt mit dem passenden Service kommunizieren kann. Wo genau diese Komplexität steckt hat IMHO keinen Einfluss auf den Programmieraufwand (obwohl der Code in der libc sich vielleicht leichter debuggen lässt als Code in einem Service oder gar im Kernel).

Denn meine Frage ist: Wenn ich schon eine gut funktionierende API im Userspace habe - warum dann nicht die gleichen Konzepte auch im Kernel verwenden?
Das klingt nach Monolith. Mein Frage ist: Geht es nicht besser/performanter wenn ich ein API benutze das auf die entsprechende Aufgabe passend zugeschnitten ist? Eben ein Stream-API für Streams oder ein File-API für Files oder ein Socket-API für Sockets (natürlich für TCP und UDP getrennt).

Prinzipiell musst du ja "nur" die IPC-Kommunikation über Sockets machen, die du miteinander verbinden kannst. Das heißt, dein Prozess redet via libc mit dem VFS, das VFS kriegt mit, dass der Plattentreiber gemeint ist und verbindet diese Deskriptoren quasi-miteinander, so dass die Kommunikation nicht mehr über das VFS läuft. Wenn der Plattentreiber nicht mehr kann oder will (z.B. nicht im HD-Treiber implementierte Funktion wie "cd"), gibt er den Deskriptor zurück an das VFS, was dann damit machen kann, was es will.
Ich hab zwar keine Ahnung was du da genau meinst aber das Ende eines Kommunikationskanals (Pipe o.ä.) durch die Gegend zu reichen stelle ich mir nicht sonderlich geschickt vor.

Kann dein Kernel das, ist die libc einfacher. Andersrum gilt entsprechendes.
Exact, kann meine libc das ist der Kernel einfacher und da ich nicht "den Kernel" habe ist es wohl eindeutig welcher Weg der bessere ist.

Wenn man kein durchreichen der Daten will dann benötigt man eine zentrale Stelle im System, da bietet sich zwar der VFS an aber IMHO ist das nicht seine Aufgabe, man würde ihm eigentlich fremde Arbeit aufbürden nur weil man versucht alles auf Dateien abzubilden.
Richtig.
Danke.

Wenn du aber dem VFS die Möglichkeit gibst, allgemeingültig "alles" auf Dateien abzubilden, dann sparst du dir in anderen Layern sehr viel Arbeit, wenn du dieses Konzept gründlich umsetzt.
Dafür habe ich diese Arbeit im VFS und der hat dann bei einem Micro-Kernel-OS das Problem für Nicht-Datei-Dienste alles weiter zu leiten. Ich versuche lieber jedes Ding möglichst simpel zu halten, der VFS kann nur Dateien, der TCP-Service nur TCP, der UDP-Service nur UDP, der RS232-Treiber stellt nur Streams bereit und die libc ist nur ein Verteiler der mit ein paar IPC-Stubs zusammen gelinkt wird.


Dann hast du gerade kein XML verwendet, sondern eine XML-ähnliche, eigene Markup-Language. Guck mal in die XML-Spec, was du für XML alles können musst!
Wieso soll das kein XML gewesen sein? (und selbst wenn nicht ist mir das auch egal) Wenn ich mir die Mühe gemacht hätte eine DTD zu schreiben hätte ich die Config-Dateien sicher auch validieren können. Ich habe nur meinen Code auf genau das beschränkt was ich auch tatsächlich benötigte (wimre 6 oder 7 Elemente mit jeweils 0 bis 2 Attributen und eben deren Inhalt).


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 #48 am: 08. October 2010, 12:11 »
Ich habe mir mal den MINIX-Source und Windows-Aufrufe angeguckt und es läuft darauf hinaus, das der VFS-Service einen neuen Prozess startet.

Man richtet also die Anfrage, einen neuen Prozess zu starten, an den VFS-Service. Dieser kann dann (wenn nötig/gewollt) irgendwelche Handles an den Kindprozess weitervererben.

Soweit ich das bei Windows verstanden habe, würde eine Shell ein Konsolenfenster öffnen. Wenn die Shell dann ein Programm ausführt, erstellt es Pipes für Stdin/Stderr/Stdout und "vererbt" diese an den Kindprozess. Sprich wenn der Kindprozess wieder einen Prozess startet würde er auch wieder Pipes erstellen und diese "weitervererben". So entsteht unter Umständen ne tierisch lange Kette und es muss verdammt viel kopiert werden.
Was mir daran ein wenig komisch vorkommt, ist dass das auch bedeutet das jeder Prozess läuft und aus der vererbten Pipe liest und die Daten an seine Stdout Pipe weiterreicht. Das finde ich dann doch ein wenig umständlich/kompliziert.

Ich bin mir immernoch nicht sicher wie ich es denn nun umsetze. Allerdings scheinen wirklich alle OSs nur einen Handle für das Dateihandling zu nutzen und der Rest (Filepointer usw.) liegt beim VFS-Service.

Das heißt also das meine Idee so nicht klappen wird. Ich wollte es eigentlich so machen, das Dateien immer in 4K Blöcken in den Prozess gemappt werden und fread dann z.B. daraus in den Client-Buffer schreiben würde. Auch würde dann der VFS-Service sich nie um den Filepointer und solche Geschichten kümmern müssen und er hätte einfach immer nur irgendwelche Pages durch die Gegend geschoben.

Nur ist es bei dieser Idee schwierig das mit dem Vererben umzusetzen. Denn der Filepointer wäre ja beim Clienten.

Da stellt sich mir halt wieder die Frage, wo (außer bei Stdout/Stdin/Stderr) wird das Vererben angewendet? Denn wenn das wirklich nicht häufig und nur für spezielle Sachen verwendet wird, dann könnte man das auch anders lösen.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #49 am: 08. October 2010, 12:24 »
Dort, wo es dem Entwickler praktisch vorgekommen ist. Ich könnte mir vorstellen, dass bei fork ohne exec noch öfter in interessanten Fällen (also nicht stdio) darauf zurückgegriffen wird. Anders lösen kann man vieles, aber meistens bleibt dann die POSIX-Kompatibilität auf der Strecke, die du ja haben wolltest, wenn ich mich nicht täusche.

Damit du POSIX vollständig implementieren kannst, brauchst du übrigens auch noch eine Methode, zwischen laufenden Prozessen Dateideskriptoren zu verschicken.
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 #50 am: 08. October 2010, 15:34 »
Hallo,


Dort, wo es dem Entwickler praktisch vorgekommen ist.
Ich will ja nicht den Querulanten spielen aber dafür hätte ich schon gerne mal ein Beispiel.
Es fällt mir ziemlich schwer dafür eine sinnvolle Anwendungsmöglichkeit zu finden. Auf der selben Datei aus mehreren Threads (fork ohne exec ist ja so was ähnliches wie Threads, zumindest für die Datei-Handles) zu arbeiten wird auf jeden Fall zu Problemen führen. Was ist wenn einer ein seek und ein anderer ein write zur selben Zeit von verschiedenen CPUs aus aufrufen, da müsste auf jeden Fall synchronisiert werden aber für den Programmierer bleibt das Risiko das er die Reihenfolge dieser Vorgänge nicht vorhersagen kann und genau deswegen bin ich der Meinung das es für richtiges File-Descriptor-Sharing keine echte Anwendungsmöglichkeit gibt.
Anders sieht die Sache z.B. bei Log-Dateien aus, wo mehrere Threads oder Prozesse (wo möglicherweise jeder ein eigenes open gemacht hat, ganz ohne Vererbung) immer nur was hinten anhängen (also in Endeffekt das selbe wie bei stdout/stderr). Dabei spielt die Reihenfolge keine wichtige Rolle und das würde mit meinem Konzept auch wunderbar klappen (die einzelnen Prozesse müssten die Datei in einem append_only-Mode öffnen und dann müsste auch nichts geshared werden, es gibt dann in den lokalen Descriptoren keinen File-Pointer). Wenn die Reihenfolge doch eine Rolle spielt dann muss der Programmierer eh einen passenden Mechanismus selber vorsehen, genau das kann das POSIX-File-Descriptor-Sharing nicht gewährleisten.

Damit du POSIX vollständig implementieren kannst, brauchst du übrigens auch noch eine Methode, zwischen laufenden Prozessen Dateideskriptoren zu verschicken.
Da ist wieder die Frage was damit genau erreicht werden soll. Geht es um ne Art Pipe (also nur append bei Log-Dateien/stdout) dann sehe ich darin kein Problem. Sollen wirklich echte Dateien zum parallelen Zugriff benutzt werden müssten auch wieder die obigen Probleme auftreten.


Also ich bleibe dabei das mein VFS nur echte Dateien anbieten soll und das Sharing von Streams usw. in der libc gemacht wird. Für Log-Dateien soll mein VFS aber die Möglichkeit haben das mehrere Prozesse ein open auf eine Datei absetzen wenn das Flag append_only gesetzt ist, dann würde der VFS eben die append-Aufrufe der einzelnen Prozesse serialisieren (natürlich ohne auf eine bestimmte Reihenfolge zu achten). Für die Dateien soll mein VFS also 2 Möglichkeiten anbieten: einmal ein normales open (mit vollwertigen Zugriff) bei dem der File-Pointer in der libc liegt und die Datei eben nur von einem Prozess geöffnet werden kann oder ein open mit appen_only wo der Fie-Pointer (== File-Size) im VFS liegt (und nicht in der libc) und beliebig viele Prozesse die Datei öffnen dürfen (alle nur mit append_only). Zusätzliches open mit read_only soll aber immer gehen wobei dann keine File-Pointer geshared werden (wenn z.B. mehrere Compiler-Instanzen die selbe Header-Datei einlesen wollen). Echtes Vererben von richtigen Dateien möchte ich nicht unterstützen, ich glaube auch nicht das mir das zum Nachteil wird.


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 #51 am: 08. October 2010, 22:24 »
Also ich stimme erik zu, solange wie kein "vernünftiges" Bsp. genannt wird sehe ich auch keinen Sinn darin einen Diskriptor zu vererben, halt wegen der genannten Probleme.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #52 am: 09. October 2010, 10:58 »
Mir fallen da Server ein, die nach einem accept() forken, wobei dann das neue Socket im neuen Prozess weiterverwendet wird, während der ursprüngliche Prozess wieder accept() aufruft.
« Letzte Änderung: 09. October 2010, 11:00 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #53 am: 09. October 2010, 11:41 »
Hallo,


Mir fallen da Server ein, die nach einem accept() forken ...
Das ist zwar richtig hat aber nichts mit unserem Thema zu tun. Wir diskutieren gerade über das sharing von richtigen Dateien. Bitte erkläre genauer was Du meinst.


Grüße
Erik
« Letzte Änderung: 09. October 2010, 11:48 von erik.vikinger »
Reality is that which, when you stop believing in it, doesn't go away.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #54 am: 09. October 2010, 17:33 »
Das ist zwar richtig hat aber nichts mit unserem Thema zu tun.
Weil Sockets was anderes als Dateien sind und insbesondere nicht vom "VFS-Dienst" verwaltet werden?
Dieser Text wird unter jedem Beitrag angezeigt.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #55 am: 09. October 2010, 17:42 »
Zitat von: PorkChicken
Weil Sockets was anderes als Dateien sind und insbesondere nicht vom "VFS-Dienst" verwaltet werden?
Auch ;)

Aber wenn ich dein Bsp. richtig verstehe (wenn nicht gibt es die selben Probleme wie bei der gleichzeitigen Nutzung von einer Datei) dann wird der Socket ja "nur" weitergegeben, sprich der "Erstbesitzer" greift nicht mehr darauf zu? Dann gibt es auch keine Probleme.

Wir reden aber davon, das mehrere Threads/Prozesse durch ein und den selben Diskriptor auf eine Datei zugreifen und das glaube ich kaum das es wirklich verwendet wird.

Edit::

@erik

Ich glaube so langsam, das "unser" VFS-Service doch einige Sachen übernehmen muss, außer reines Dateihandling. Denn wie hast du es dir vorgestellt das Umleiten von Stdin/Stdout zu bewerkstelligen, wenn du es nicht auf Dateien abbildest?

@all

Etwas Offtopic, aber passt irgendwie doch hierher.

Wie funktioniert euer printf. Genauer bin ich daran interessiert ob ihr die Daten erst in einen "kleinen" (die Größe wäre auch interessant) Buffer schreibt und am Ende von printf einen flush() macht oder ob ihr jedes Zeichen einzeln sendet (was ich eher nicht glaube).

Ich frage das, weil ich auch schon von Problemen gehört habe, das unter Umständen die Ausgabe eines Programms erst sichtbar wird, wenn dieses beendet wird, weil erst dann ein flush() durchgeführt wird, aber jedes Zeichen einzeln zu senden ist ja auch quatsch.
« Letzte Änderung: 09. October 2010, 18:18 von FlashBurn »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #56 am: 09. October 2010, 18:32 »
stdio.h ist grundsätzlich gepuffert. Lies dir am besten mal die Doku zu setvbuf durch.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #57 am: 09. October 2010, 18:37 »
Zitat von: taljeth
stdio.h ist grundsätzlich gepuffert. Lies dir am besten mal die Doku zu setvbuf durch.
Die Frage ist dann ja, wann wird der Buffer geflusht? Wird es zu oft gemacht, ist es nicht gut für die Performance, wird es zu wenig gemacht, kommen eventuell Meldungen auf der Konsole "zu spät" an.

Da sehe ich dann die ersten Nachteile, wenn man alles auf Dateien abbildet. Denn ich würde sagen, wenn man in Dateien schreibt, kann der Buffer ruhig etwas größer sein und sollte so wenig wie möglich geflusht werden, aber was Meldungen auf der Konsole betreffen, möchte ich die so schnell wie möglich sehen, werden die aber in eine Datei umgeleitet ist wieder ein großer Buffer besser.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #58 am: 09. October 2010, 19:40 »
Mal davon abgesehen, dass ich mir nicht sicher bin, dass das immer das ist was man will: So funktioniert C eben nicht.

Standardmäßig wird stdout am Zeilenende geflusht und stderr ist komplett ungepuffert. Das halte ich auch grundsätzlich für eine vernünftige Voreinstellung, wenn man nicht irgendwelche speziellen Sachen macht. Wenn ich dasselbe Programm einmal in eine Datei umleite und einmal auf der Konsole anzeigen lasse, dann will ich auf jeden Fall in beiden Fällen dasselbe Ergebnis sehen. Auch wenn das Programm nach irgendeiner Ausgabe, die möglicherweise gepuffert ist, abstürzt.
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 #59 am: 09. October 2010, 21:34 »
Hallo,


Ich glaube so langsam, das "unser" VFS-Service doch einige Sachen übernehmen muss, außer reines Dateihandling. Denn wie hast du es dir vorgestellt das Umleiten von Stdin/Stdout zu bewerkstelligen, wenn du es nicht auf Dateien abbildest?
Also stdin/stdout/stderr sind für mich Streams und die sollen bei mir von libc zu libc direkt gehen. Wenn die Shell ein Programm startet und diesem ihre Streams (die die Shell ja auch von ihrem Aufrufer bekommen hat) mitgibt dann kommuniziert der neue Prozess direkt mit dem original-Anbieter der Streams, zumindest bei den Output-Streams stdout/stderr ist das IMHO kein Problem solange immer ordentlich geflusht wird. Oder seht ihr da doch ein Problem?
Wenn in eine Datei gestreamt werden soll dann soll von libc zu libc nicht ein Handle o.ä. sondern ein absoluter Datei-Pfad weitergegeben werden und die libc im Kind-Prozess macht ein eigenes open mit append_only, das flushen muss hier natürlich auch passend gemacht werden.

Bei den Input-Streams ist das ein kleines bisschen komplizierter, ich habe mir das so vorgestellt das bei Streams immer die Daten-Quelle aktiv die Daten zum Ziel sendet (also per IPC weitergibt) und nicht das Ziel ständig bei der Quelle nachfragt (getch() usw. wären dann blockierende Funktionen in der libc und der blockierte Thread würde vom IPC-Stub aufgeweckt werden wenn Daten kommen). In meinem Konzept würde das bedeuten das wenn aus einer Datei gestreamt wird und der Kind-Prozess mit den ersten x kBytes angetriggert wurde dieser aber nur die ersten 50 Bytes entnommen hat und dann seinerseits ein Kind startet dann muss er antworten "ich habe nur 50 Bytes entnommen und jetzt schicke erst mal bis auf weiteres an XYZ". Daraufhin betrachtet die Quelle die ersten 50 Bytes als entnommen (der Lese-Pointer wird weiter gesetzt) und probiert es wieder mit x kBytes (ab Offset 50) beim neuen Abnehmer (dank meinem IPC geht das alles ohne das irgendwas kopiert werden musste). Wenn ein Kind beendet wird dann muss es der Quelle sagen das es nichts mehr haben will und die Quelle probiert es dann wieder beim vorherigem Ziel (LIFO). Wenn die Shell ein Kind startet und dessen stdin aus einer Datei kommen soll dann ist eben die Shell die Quelle, in der libc muss dafür ein Hintergrund-Thread gestartet werden der die aktive Quelle spielt (also aus Datei lesen und an Kind senden, auch hier muss nichts kopiert werden).
Wie ist das eigentlich wenn man stdin weiter vererbt, darf man dann trotzdem getch() machen? Eigentlich käme da ja unvorhersehbarer Quatsch raus. Ich bin daher der Meinung dass das nicht funktionieren muss. Was sagt POSIX dazu?

Ich denke mit diesem Weg schaffe ich eine hohe Performance weil keine langen Ketten zum durch reichen da sind, alles mit Zero-Copy läuft und habe trotzdem die Sicherheit das nichts verloren geht. Ich sehe auch kein Problem das in der libc zu verstecken.


Das printf wenigstens am Ende flusht finde ich auch gut, ich denke bei stdout und erst recht bei stderr geht Sicherheit vor Performance. Wer große Datenmengen schnell los werden will wird sich auch was passendes einfallen lassen.


@taljeth: Du bist uns immer noch ein Beispiel für echtes Datei-Descriptor-Sharing schuldig.


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

 

Einloggen