Autor Thema: Shared Memory  (Gelesen 51667 mal)

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« am: 19. September 2010, 17:48 »
Ich bin gerade über einen Bug in meinem Shared Memory Code gestolpert und bin mir bei einer Sache nicht ganz sicher wie man es am besten macht.

Mein Shared Memory funktioniert so, das ein Prozess einen Bereich als SharedMemory erstellen kann (sprich der Speicher dafür muss schon im Prozess vorhanden sein). Will er (der Prozess) anderen Prozessen den Zugriff auf den Speicher geben, muss er einen "SharedAllow"-Syscall aufrufen, dem er die Adresse des Shared Memory und des Ziel-Prozesses übergibt.
Der Zielprozess ruft dann einen "SharedMap"-Syscall auf mit der ID des SharedMemory, hat er seine Arbeit erledigt ruft er den "SharedUnmap"-Syscall auf.

Mit dem letztgenannten Syscall (SharedUnmap) hab ich dann so meine Probleme. Im Moment habe ich nen Counter wie oft ein Shared Memory Bereich irgendwo gemappt ist und nur wenn dieser Counter "0" wird, wird die ganze Strukur (die die Daten zur Beschreibung des Shared Memory beinhaltet) wieder freigegeben/gelöscht.
Nur kann es jetzt die Situation geben, das ein anderer Prozess noch gar nicht an der Reihe war (zwecks Scheduling-Strategie) und den Speicher noch nicht mappen konnte. Dadurch würde diese Shared Memory nicht mehr existieren und der Empfänger würde nen Fehler zurückbekommen.
Das ist natürlich unschön. Wenn ich sage das ein Shared Memory solange exisitiert bis alle Prozesse, die in der "Allow"-Liste stehen, diesen auch einmal gemappt und dann wieder geunmappt haben, mache ich mir sorgen um die Sicherheit bzw. würde ich das dann fast schon als Speicherleck sehen.

Was meint ihr wie man das lösen sollte?

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 20. September 2010, 12:18 »
Ich denke ich werde es so lösen, wie ich es momentan schon habe, sprich wenn kein Prozess mehr den Speicher gemappt hat, dann wird die SharedMemory Struktur gelöscht. Denn würde ich das nicht machen, wäre es ganz einfach mein OS zum stillstand zu bringen, in dem man einfach nen SharedMemory Bereich erstellt, nen anderen Prozess auf die Allow-Liste packt, den Bereich unmappt und dann wieder nen neuen Bereich erstellt und von vorne anfängt, so lange bis kein physischer Speicher mehr vorhanden ist.

Man (als Prozess der den SharedMemory erstellt) muss dann halt nur sicher stellen, das man es irgendwie bei der Kommunikation so macht, das der SharedMemory erst geunmappt wird, wenn der Ziel-Prozess diesen auch gemappt hat.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #2 am: 20. September 2010, 17:02 »
Das ist natürlich unschön. Wenn ich sage das ein Shared Memory solange exisitiert bis alle Prozesse, die in der "Allow"-Liste stehen, diesen auch einmal gemappt und dann wieder geunmappt haben, mache ich mir sorgen um die Sicherheit bzw. würde ich das dann fast schon als Speicherleck sehen.
Ich seh da kein Speicherleck, der Prozess braucht ja nicht den Weg über shared-memory gehen um dein "Leck" zu erzeugen, er kann einfach wie wild Speicher allozieren und nie mehr freigeben.
Ich würde lieber den Weg mit der Allow-Liste einschlagen, denn IPC ist schon so schwer genug, da macht es keinen Spaß auch noch auf so ein Timing-Problem Rücksicht zu nehmen (va. wenn es in keinster Weise irgendein anderes Problem löst). Aber ich würde natürlich einen noch-nicht-angenommenen Shared-memory Bereich dem Prozess als verbrauchter Speicher anrechnen. Damit wird dein Shared-memory "Speicherleck" einfach nur zu einem normalen "Speicherleck".

Worauf du aber achten solltest, wenn du jeden Speicherbereich zu shared-memory machen kannst, ist, dass du nicht einfach mit dem anderen Prozess Dinge sharest, die du eigentlich nicht sharen wolltest, nur weil sie auf der selben Page liegen.
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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 20. September 2010, 17:16 »
Zitat von: bluecode
Worauf du aber achten solltest, wenn du jeden Speicherbereich zu shared-memory machen kannst, ist, dass du nicht einfach mit dem anderen Prozess Dinge sharest, die du eigentlich nicht sharen wolltest, nur weil sie auf der selben Page liegen.
Das ist ein Problem des App-Programmierers und nicht des OS. Denn SharedMemory läuft nunmal nur über Pages.

Zitat von: bluecode
Ich seh da kein Speicherleck, der Prozess braucht ja nicht den Weg über shared-memory gehen um dein "Leck" zu erzeugen, er kann einfach wie wild Speicher allozieren und nie mehr freigeben.
Wenn ich mal davon ausgehe, das ich irgendwann Swappen kann, dann kannst du mein OS nur ärgern, wenn der Speicher auch nicht ausgelagert wird und das ist nur bei SharedMemory der Fall.

Zitat von: bluecode
Ich würde lieber den Weg mit der Allow-Liste einschlagen, denn IPC ist schon so schwer genug, da macht es keinen Spaß auch noch auf so ein Timing-Problem Rücksicht zu nehmen
Oder ich müsste mir noch was einfallen lassen, so dass man Pages von einem Prozess zu einem anderem Prozess verschieben/schicken kann. Dieser Speicher würde dann auch beim Sender "ausgetragen" werden.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #4 am: 20. September 2010, 18:57 »
Zitat von: bluecode
Worauf du aber achten solltest, wenn du jeden Speicherbereich zu shared-memory machen kannst, ist, dass du nicht einfach mit dem anderen Prozess Dinge sharest, die du eigentlich nicht sharen wolltest, nur weil sie auf der selben Page liegen.
Das ist ein Problem des App-Programmierers und nicht des OS. Denn SharedMemory läuft nunmal nur über Pages.
Natürlich läuft das über Pages. Aber ich fand es sinnvoller spezielle Bereiche (die komplett vom Heap entkoppelt sind) für shared-memory vorzusehen, d.h. man kann sowas schon nicht mit new/malloc allozieren, sondern ruft da schon den Kernel auf. Ich find das mit malloc/new irgendwie sinnlos, da das free/delete beim Freigeben sowieso irgendwas shared-memory spezifisches machen muss (die Regionen werden ja nach dem Versenden irgendwie vom Kernel verwaltet) und man es dann auch nicht einfach wieder in die Freispeicherliste (oder was auch immer) eintragen kann, da ein anderer Prozess das ganze noch nutzt. Soll heißen, die Heapverwaltungsstrukturen auf einer shm Page sind für shared-memory überflüssig und im schlimmsten Fall kann dadurch ein anderer Prozess meinen Heap kaputtmachen. Abgesehen davon ist es für den Anwendungsenwickler einfach nur fricklig irgendwas mit align 4096 über malloc/new zu allozieren.
Wie gesagt, meine Lösung war das komplett von der Heapverwaltung zu entkoppeln.

Zitat
Zitat von: bluecode
Ich seh da kein Speicherleck, der Prozess braucht ja nicht den Weg über shared-memory gehen um dein "Leck" zu erzeugen, er kann einfach wie wild Speicher allozieren und nie mehr freigeben.
Wenn ich mal davon ausgehe, das ich irgendwann Swappen kann, dann kannst du mein OS nur ärgern, wenn der Speicher auch nicht ausgelagert wird und das ist nur bei SharedMemory der Fall.
Warum sollte das mit shared-memory nicht funktionieren, va. warum nicht in dem von dir beschriebenen Szenario?

Zitat
Zitat von: bluecode
Ich würde lieber den Weg mit der Allow-Liste einschlagen, denn IPC ist schon so schwer genug, da macht es keinen Spaß auch noch auf so ein Timing-Problem Rücksicht zu nehmen
Oder ich müsste mir noch was einfallen lassen, so dass man Pages von einem Prozess zu einem anderem Prozess verschieben/schicken kann. Dieser Speicher würde dann auch beim Sender "ausgetragen" werden.
Ich hab das mit dem verschicken in lightOS implementiert. Das ist so implementiert, dass man mit einer IPC-Message einen shared-memory Bereich mitschicken kann. Möglich war dabei, dass der Speicher aus dem Sender geunmappt wird (also ein kompletter Ownershiptransfer) oder Read-only oder Read-Write zu versenden.
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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 20. September 2010, 20:33 »
Zitat von: bluecode
Wie gesagt, meine Lösung war das komplett von der Heapverwaltung zu entkoppeln.
Irgendwo müssen wir uns gegenseitig missverstanden haben, denn das es nichts mit der Heapverwaltung zu tun hat ist klar. Das ist bei mir genauso, aber ich weiß worum es geht, nämlich das man erstmal den Speicher zum sharen braucht.
Dafür würde ich dann sagen, ruft das Programm halt den selben Syscall auf wie malloc auch (um 1 oder mehrere Pages zu allozieren).

Zitat von: bluecode
Warum sollte das mit shared-memory nicht funktionieren, va. warum nicht in dem von dir beschriebenen Szenario?
Weil ich bei SharedMemory grundsätzlich sage, das es nicht geswappt wird. Denn dann müsste ich im average-case in 2 und im worst-case in noch mehr Prozessen in den PageTables rumspielen und das wird verdammt schwierig, weil auch mein Kernel immer nur die PageTables sieht von dem Prozess der gerade läuft.
Swappen wird sowieso interessant zu implementieren, da ja die Treiber und die VFS Sachen alle im UserSpace laufen (werden).

Zitat von: bluecode
Ich hab das mit dem verschicken in lightOS implementiert. Das ist so implementiert, dass man mit einer IPC-Message einen shared-memory Bereich mitschicken kann. Möglich war dabei, dass der Speicher aus dem Sender geunmappt wird (also ein kompletter Ownershiptransfer) oder Read-only oder Read-Write zu versenden.
Naja, da ich ja nur fixed-size Nachrichten habe (haben möchte) müsste ich mal sehen, ob ich das als Nachricht oder irgendwie anders machen würde.
Eventuell als ne spezielle Art von Nachricht, nur wie ich das dem Empfänger signalisiere wüsste ich jetzt spontan nicht. Denn was in so einer Nachricht steht ist bei mir nicht festgelegt und von daher habe ich auch nicht sowas wie nen Msg-Code mit dem man die Nachricht bzw. deren Inhalt identifizieren könnte.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 22. September 2010, 17:34 »
Ich habe mir überlegt eine spezielle Nachricht bzw. einen speziellen Sender zu verwenden um Speicher von einem Prozess zu einem anderen zu senden.

Ich wollte mir jetzt nur mal euren "Segen" holen ob man das so machen kann/sollte oder nicht.

Bei mir kann es als Sender-ID keine "0" geben und diesen Sender wollte ich dann für spezielle Nachrichten verwenden. Sprich als Sender-ID bekommt der Receiver ne "0" und in der Nachricht wäre der erste 32bit-Wert ein Nachrichten-Code und ich würde diese speziellen Nachrichten für irgendwelche System-Nachrichten nutzen.
In diesem speziellen Fall wäre der Code halt das man Speicher von einem anderen Prozess bekommen hat und der zweite 32bit-Wert wäre die Adresse wo dieser Speicher hingemappt wurde.

Soweit so gut. Was mache ich aber, wenn im Adressraum des Receivers nicht genug virtueller Speicher vorhanden ist um den Speicher zu mappen?
Da das ganze ja asynchron wäre, könnte man dem Sender nicht mal sagen, dass der Speicher nicht gemappt werden konnte, das wäre ja noch nicht mal weiter Schlimm.
Aber was passiert mit dem Speicher der gemappt werden sollte, im Adressraum des Senders ist er nicht mehr und in den Adressraum des Receivers passt er nicht rein, also weg damit?
Eine Möglichkeit wäre, die Nachricht (irgendwie) synchron zu machen, sprich der Sender sollte (er muss nicht) auf eine Nachricht des Receivers warten. Ich (als Kernel) würde dann also eine Nachricht an den Sender schicken, wenn der Speicher gemappt werden konnte, das alles Ok ist. Wenn der Speicher nicht gemappt werden konnte, steht halt in der Nachricht der Code für "konnte nicht gemappt werden" drin und die Adresse wo ich (als Kernel) den Speicher wieder zurück gemappt habe.
Gut wäre eine Lösung, was passiert jetzt aber, wenn der virtuelle Speicher des Sender inzwischen auch so voll ist das der Speicher nicht wieder zurück gemappt werden kann?

Wie ihr seht habe ich ein Problem mit der Fehlerbehandlung bzw. ob es richtig ist den Speicher der versendet werden soll im Fehlerfall einfach wieder freizugeben als hätte es ihn nie gegeben.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #7 am: 22. September 2010, 18:31 »
hm, du könntest ja beim Senden schon den virtuellen Speicher im anderen Prozess reservieren (ohne zu mappen, falls das zuviel Probleme macht) und dann dem Sender zurückliefern, dass zumindest das geklappt hat. Dann kann der sich überlegen ob er es später nochmal versucht oder einfach aufgibt.

Aber eigentlich sollte das bei einem Hobby-OS eher kein Problem werden, denke ich. :wink:
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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 22. September 2010, 18:54 »
Zitat von: bluecode
hm, du könntest ja beim Senden schon den virtuellen Speicher im anderen Prozess reservieren (ohne zu mappen, falls das zuviel Probleme macht) und dann dem Sender zurückliefern, dass zumindest das geklappt hat.
Da wären wir wieder bei dem Problem das ich vom Sender aus nicht in die PageTables (bzw. meine anderen Datenstrukturen die dafür verwendet werden) reingucken kann und dann kommt noch hinzu, wenn ich den virtuellen Speicher reservieren kann, dann kann ich ihn auch mappen (es geht ja nur um ein "Stück" was groß genug ist, das der Speicherbereich, der gesendet werden soll, reinpasst).

Zitat von: bluecode
Aber eigentlich sollte das bei einem Hobby-OS eher kein Problem werden, denke ich.
Ist zwar richtig, sollte aber trotzdem irgendwie behandelt werden.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 22. September 2010, 19:04 »
Hallo,


also ich würde in dem Sende-Syscall erst den Speicher ins Ziel mappen und danach erst beim Sender unmappen. Wenn das mappen beim Ziel nicht klappt dann kommt der Syscall mit einem Error-Code zurück und der Speicher ist noch beim Sender.
Physischer Speicher ohne Besitzer ist IMHO ein Bug im Kernel. ;)


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 #10 am: 22. September 2010, 19:19 »
Zitat von: erik
also ich würde in dem Sende-Syscall erst den Speicher ins Ziel mappen und danach erst beim Sender unmappen. Wenn das mappen beim Ziel nicht klappt dann kommt der Syscall mit einem Error-Code zurück und der Speicher ist noch beim Sender.
Wenn ich das als eigenen Syscall machen (also nicht über den sendMsg Syscall) dann dürfte das selbst bei meinem IPC System hinzubekommen sein.

Problematisch ist halt nur, dass das ganze dann halt blockierend wäre, was ich eher unschön finde, aber das könnte man ja über ein Flag lösen!

Zitat von: erik
Physischer Speicher ohne Besitzer ist IMHO ein Bug im Kernel.
Da hast du mich dann nicht ganz verstanden, wenn der Speicher nicht gemappt werden konnte, wird er einfach freigegeben als wenn es ihn nie gegeben hätte ;)

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 22. September 2010, 21:10 »
Hallo,


Wenn ich das als eigenen Syscall machen (also nicht über den sendMsg Syscall) dann dürfte das selbst bei meinem IPC System hinzubekommen sein.
Warum sollte das nicht gleich der SendMSG-Syscall machen?

Problematisch ist halt nur, dass das ganze dann halt blockierend wäre, was ich eher unschön finde, aber das könnte man ja über ein Flag lösen!
Der Syscall soll doch nur so lange blockieren bis das ummappen erledigt ist, so lange wird das schon nicht dauern.

Da hast du mich dann nicht ganz verstanden, wenn der Speicher nicht gemappt werden konnte, wird er einfach freigegeben als wenn es ihn nie gegeben hätte
Das ist aber auch nicht gerade höflich wenn Speicher einfach so verschwindet. Was ist wenn der Client es noch mal probieren will? Dann muss er neuen Speicher allozieren und neu mit Daten befüllen, das stelle ich mir unpraktisch vor.


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 #12 am: 22. September 2010, 21:31 »
Zitat von: erik
Warum sollte das nicht gleich der SendMSG-Syscall machen?
Naja, wird schwierig, weil zusätzliche Parameter (die bei den meisten Aufrufen total Sinnlos wären) und wie gesagt macht sich das über nen eigenen Syscall einfacher (zumindest die Idee die ich gerade im Kopf dazu habe).

Zitat von: erik
Der Syscall soll doch nur so lange blockieren bis das ummappen erledigt ist, so lange wird das schon nicht dauern.

Das ist aber auch nicht gerade höflich wenn Speicher einfach so verschwindet. Was ist wenn der Client es noch mal probieren will? Dann muss er neuen Speicher allozieren und neu mit Daten befüllen, das stelle ich mir unpraktisch vor.
Ich habe mir das nochmal genau überlegt, an und für sich, fordert der Client ja den Speicher an, d.h. er weis wie groß der Bereich ist, soll heißen er wird das nur machen wenn er auch genug freien virtuellen Speicher hat.
Daher kann man sagen, das der Fall das es nicht gemappt werden kann eher selten bis gar nicht auftreten sollte (was man aber bei Multithreading nicht so einfach sagen kann).
Was das Blockieren betrifft, das sollte (unter den selben Betrachtungspunkten wie Oben, sprich der Client wartet darauf) eigentlich auch nicht lange dauern (wie du schon sagtest).

Sprich ich werd es trotzdem mit nem Flag machen, das der Sender nicht blockiert und ich werde nen eigenen Syscall dafür machen (ist einfach einfacher ;) und performanter).

Jetzt komme ich dem zero-copy immer näher ;)

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #13 am: 23. September 2010, 10:33 »
Zitat von: bluecode
hm, du könntest ja beim Senden schon den virtuellen Speicher im anderen Prozess reservieren (ohne zu mappen, falls das zuviel Probleme macht) und dann dem Sender zurückliefern, dass zumindest das geklappt hat.
Da wären wir wieder bei dem Problem das ich vom Sender aus nicht in die PageTables (bzw. meine anderen Datenstrukturen die dafür verwendet werden) reingucken kann und dann kommt noch hinzu, wenn ich den virtuellen Speicher reservieren kann, dann kann ich ihn auch mappen (es geht ja nur um ein "Stück" was groß genug ist, das der Speicherbereich, der gesendet werden soll, reinpasst).
Um virtuellen Speicher zu allozieren muss man nicht in die PageTables schauen. Dafür wird man wohl sowieso andere geeignete Datenstrukturen verwenden, z.B. Buddy. Es läuft doch niemand (zumindest hoffe ich das) wie bei einer Bitmap durch die PageTables und sucht nach einem passend großen Stück virtuellen Speichers...

Zitat
Daher kann man sagen, das der Fall das es nicht gemappt werden kann eher selten bis gar nicht auftreten sollte
Der Fall tritt ja schon allein, weil es nur ein Hobby-OS ist, wohl eher nicht auf. Oder werden da fette Datenbanken oä. auf der 32Bit Version laufen. :-P
« Letzte Änderung: 23. September 2010, 10:35 von bluecode »
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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 23. September 2010, 10:46 »
Zitat von: bluecode
Um virtuellen Speicher zu allozieren muss man nicht in die PageTables schauen. Dafür wird man wohl sowieso andere geeignete Datenstrukturen verwenden, z.B. Buddy. Es läuft doch niemand (zumindest hoffe ich das) wie bei einer Bitmap durch die PageTables und sucht nach einem passend großen Stück virtuellen Speichers...
Ich benutze weder Buddy noch gehe ich die PageTables durch, aber wie gesagt, diese Datenstrukturen sind Prozessbezogen und nur dann "sichtbar" wenn der Prozess auch läuft. Man kann auf diese Daten nicht von einem anderem Prozess aus zugreifen.

Zitat von: bluecode
Der Fall tritt ja schon allein, weil es nur ein Hobby-OS ist, wohl eher nicht auf. Oder werden da fette Datenbanken oä. auf der 32Bit Version laufen.
Auch hier wieder, nur weil es auf einem HobbyOS unwahrscheinlich ist/erscheint, sollte man den Fall trotzdem "bearbeiten" können.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 23. September 2010, 11:48 »
Hallo,


Der Fall tritt ja schon allein, weil es nur ein Hobby-OS ist, wohl eher nicht auf. Oder werden da fette Datenbanken oä. auf der 32Bit Version laufen.
Was soll das denn Bitte bedeuten? Das auf einem Hobby-OS nicht auch mal sehr speicherintensive Programme gestartet werden? Du kennst doch bestimmt 7z und die LZMA-Library, das ist ein ziemlich speicherintensives Programm welches sich wohl sehr leicht portieren lässt.


Jetzt komme ich dem zero-copy immer näher
Das sehe ich noch nicht, solange die Clients sich extra neuen Speicher holen müssen (weil dieser ja wegen dem IPC weggenommen wird) und ihn extra mit Daten befüllen müssen (also kopieren) nur um IPC machen zu können bist Du IMHO noch nicht bei Zero-Copy! Oder habe ich was übersehen?
Außerdem sehe ich da eine Menge Syscalls für die Clients: Speicher holen, IPC antriggern, Speicher mitgeben, Antwort abholen und eventuell noch Speicher zurückholen.


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: 23. September 2010, 13:08 »
Zitat von: erik
Das sehe ich noch nicht, solange die Clients sich extra neuen Speicher holen müssen (weil dieser ja wegen dem IPC weggenommen wird) und ihn extra mit Daten befüllen müssen (also kopieren) nur um IPC machen zu können bist Du IMHO noch nicht bei Zero-Copy! Oder habe ich was übersehen?
Außerdem sehe ich da eine Menge Syscalls für die Clients: Speicher holen, IPC antriggern, Speicher mitgeben, Antwort abholen und eventuell noch Speicher zurückholen.
Um es mal am Bsp. des HDD-Treibers zu "zeigen".

Du musst Speicher holen damit der HDD-Kontroller weis wo er die Daten hinladen soll (das wirst du bei dir wohl auch machen müssen).
Hat er die Daten dann in diesen Speicher geladen, wird er mit einem Syscall per Nachricht zum VFS-Service geschickt.
Wie dieser dann die Daten an den Clienten weiterreicht ist erstmal unwichtig, denn da müsste man viele Fälle betrachten (nur wenige Bytes, eine ganze Datei, die gemappt werden könnte, ...).

Ich denke du versuchst dein IPC auf mein IPC abzubilden ;)

Bei meinem IPC schickst du keinen "Speicher" mit wo die Daten reinkommen, du bekommst ihn und das RPC bei mir auch mit einem Syscall gemacht wird, weist du ja eigentlich.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 23. September 2010, 14:19 »
Hallo,


Du musst Speicher holen damit der HDD-Kontroller weis wo er die Daten hinladen soll (das wirst du bei dir wohl auch machen müssen).
Also bei mir gibt der Client immer den Speicher mit, egal ob gelesen oder geschrieben werden soll.

Wie dieser dann die Daten an den Clienten weiterreicht ist erstmal unwichtig, denn da müsste man viele Fälle betrachten (nur wenige Bytes, eine ganze Datei, die gemappt werden könnte, ...).
Bis auf das Datei-Mapping (was auch was völlig anderes als fread/fwrite ist) geht alles bei mir über den selben Mechanismus, egal ob nur 3 Bytes oder ganze 3 GBytes, egal ob ausgerichtet oder nicht.
One way fits all! :-D

Ich denke du versuchst dein IPC auf mein IPC abzubilden ;)
Etwas vielleicht, ich versuche zumindest die Möglichkeiten meines Konzepts auch in Deinem Konzept wieder zu finden, aber eben nur mit wenig Erfolg. Sorry.

Bei meinem IPC schickst du keinen "Speicher" mit wo die Daten reinkommen, du bekommst ihn
Das deckt sich aber nicht mit fread (das bekommt einen Pointer wo die Daten hin sollen und liefert nicht einen Pointer zurück wo das System die Daten hingelegt hat) und auch sonst keinem der üblichen SW-Paradigmen, da wirst Du wohl viel kopieren müssen in Deiner libc. Bei fwrite wird auch ein Pointer mitgegeben aber die Daten verschwinden nicht sondern bleiben dem Prozess unverändert erhalten. Ausgerichtet sind die Pointer für fread/fwrite üblicherweise auch nicht, wenn Du also immer ganze Pages mitgeben willst dann hast Du Probleme die dann auch wieder auf kopieren hinauslaufen.
Sorry, aber Zero-Copy sehe ich in Deinem Konzept nicht. Was nicht heißt das ich Dein Konzept auch sonst wie schlecht finde, es ging mir heute nur um das Zero-Copy.


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: 23. September 2010, 14:37 »
Zitat von: erik
Sorry, aber Zero-Copy sehe ich in Deinem Konzept nicht. Was nicht heißt das ich Dein Konzept auch sonst wie schlecht finde, es ging mir heute nur um das Zero-Copy.
Ich denke wir sollten uns darauf einigen, das es unter Paging kein "immer zero-copy möglich" gibt! Man macht halt das beste daraus.

Zitat von: erik
Das deckt sich aber nicht mit fread (das bekommt einen Pointer wo die Daten hin sollen und liefert nicht einen Pointer zurück wo das System die Daten hingelegt hat) und auch sonst keinem der üblichen SW-Paradigmen, da wirst Du wohl viel kopieren müssen in Deiner libc.
Naja, bei nem Mikrokernel der mehr mikro ist als das was man heute als solche bezeichnet (z.B. Haiku) wird man um einiges an kopieren nicht vorbei kommen.

Wie gesagt, sehe ich auch mit Paging-Tricks, wie dem reinmappen und nur den Rand kopieren, nicht das man das irgendwie "zufriedenstellend" lösen könnte.

Zitat von: erik
Bis auf das Datei-Mapping (was auch was völlig anderes als fread/fwrite ist) geht alles bei mir über den selben Mechanismus, egal ob nur 3 Bytes oder ganze 3 GBytes, egal ob ausgerichtet oder nicht.
Nicht dass das hierher gehören würde, aber mich würde mal interessieren wie du folgendes löst.

FILE *file= fopen("foobar","r");
char buffer[512], *ptr= &buffer;

for(uint32t x= 0; x < 512/4; x++) {
 fread(ptr,sizeof(uint32t),1,file);
 fseek(file,12,SEEK_CUR);
 ptr+= sizeof(uint32t);
}
Mir geht es bei diesem (sinnlosen??) Bsp darum, dass du ja immer den Speicher mitgibts wo die Daten reinsollen, wie bekommst du aber die Daten aus dem Sektor, der zu der Stelle in der Datei gehört, ohne kopieren in den Buffer?

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 23. September 2010, 15:09 »
Hallo,


Ich denke wir sollten uns darauf einigen, das es unter Paging kein "immer zero-copy möglich" gibt! Man macht halt das beste daraus.
[.....]
Wie gesagt, sehe ich auch mit Paging-Tricks, wie dem reinmappen und nur den Rand kopieren, nicht das man das irgendwie "zufriedenstellend" lösen könnte.
Also ich würde schon sagen dass das mit "nur den Rand kopieren" recht zufriedenstellend ist, besser geht es eben nur mit Paging nicht. Insofern hat man zumindest ein "fast immer ohne kopieren". Alternativ könnte man auch definieren das einem dieses kleine Sicherheitsrisiko egal ist und immer komplette Pages gemappt werden so das man dann doch "immer ohne kopieren" bekommt.

Mir geht es bei diesem (sinnlosen??) Bsp darum, dass du ja immer den Speicher mitgibts wo die Daten reinsollen, wie bekommst du aber die Daten aus dem Sektor, der zu der Stelle in der Datei gehört, ohne kopieren in den Buffer?
Nichts leichter als das! :-D
Ich lasse den Sektor in 3 verschiedene Bereiche vom AHCI-Controller reinlesen. Der interessante Teil kommt in die User-Daten und der Rest in einen 512Byte kleinen Trash-Buffer (welcher im Treiber liegt und immer ignoriert wird).
Selbst wenn die 4 Bytes z.B. an Datei-Offset 1021 liegen und an Speicher-Offset 4095 sollen und dort ne Pagegrenze ist und die Pages nicht zusammenhängend im physischen Speicher liegen ist das kein Problem. Die ersten 509 Bytes (der insgesamt 1024 Bytes von der HDD) kommen in den Trash-Buffer, das nächste Byte kommt ans Ende der ersten User-Page, anschließend 3 Bytes an den Anfang der zweiten User-Page (das in diesen 3 Bytes die Sektorgrenze ist spielt für AHCI keine Rolle) und zum Schluss noch 511 Bytes in den Trash-Buffer.
Das dieses Beispiel natürlich vom Cache im VFS abgefangen wird hab ich jetzt mal ignoriert, es geht uns doch ums Zero-Copy-Prinzip.


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

 

Einloggen