Hallo,
Niemand hindert den Callee daran, den Speicher selbst freizugeben und den Caller per asynchronem IPC darüber zu informieren.
Das ist zwar richtig aber es erscheint mir irgendwie umständlich, aus meiner Sicht ist das ganze ein kompletter IPC/RPC-Vorgang den ich auch so als asynchrones IPC anbieten möchte. Bei mir wird zuerst das Memory-Sharing eingerichtet und dann beim Callee ein PopUp-Thread injiziert aber der Caller blockiert nicht bis der Callee fertig ist sondern kann weiter arbeiten, wenn der Callee fertig ist wird das Memory-Sharing beendet und beim Caller auch ein PopUp-Thread injiziert der dann den Call-Back ausführt.
Willst du etwa eine vorhandene libc portieren?
Nein, das will ich nicht, was ich meinte war eher dass das API der libc eben auch auf dieses Paradigma setzt. Das bedeutet z.B. das read die gelesenen Daten nicht in einem neuen Speicherbereich als Rückgabewert liefert sondern das der Speicherbereich in den die Daten rein sollen schon vorgegeben wird.
Kann jedes PCI-Gerät überhaupt 64-Bit-DMA benutzen? Würde ich jedenfalls wundern.
Bei
nativen PCI-Express-Geräten ist es vorgeschrieben, bei
legacy PCI-Express-Geräten ist das freiwillig. Bei xHCI und ACHI müssen alle Geräte das unterstützen, GBit-Ethernet-Controller wohl auch (zumindest die aus gutem Hause). Echtes Profi-Equipment (SAS / 10GBit-Ethernet / Infiniband / ....) der letzten 10 Jahre sollte das ebenfalls können. Was als Unsicherheit bleibt ist irgendwelcher Billig-Ramsch und all jenes Zeugs das man unter "Sonstiges" einsortiert, aber selbst dort denke ich das in den letzten 5 Jahren die Mehrheit 64Bit-DMA können sollte. Bis ich wirklich echte Hardware zum Ausprobieren habe wird die Einschränkung auf 64Bit-DMA jedenfalls keine Einschränkung mehr sein, wäre es auch Heute schon nicht.
Das VFS sollte mit beiden Varianten klarkommen, von daher spielt das keine Rolle.
Aus Sicht des VFS spielt das IMHO schon eine Rolle, wenn sämtliche Dateioperationen über ein einziges Handle laufen dann ist die Kohärenz doch schon innerhalb der Anwendung erledigt, egal wie viele Threads die Anwendung hat.
nicht aber auf Senderseite, aber dann kann man auch nicht auf eine Nachricht antworten.
Also wenn man für synchrones IPC (also alles was eine zugehörige Antwort hat) bereits einen eigenen Port benötigt um auch nur als Client funktionieren zu können ist das IMHO schon eine Einschränkung, die meisten (einfachen) Funktionen aus der libc sind synchron (und blockierend). Wie viele libc-Funktionen kennst Du die keinen Rückgabewert haben?
Hmm, spontan würde ich sagen, einfach durch aio_read()/aio_write() nen neuen Thread erstellen, der dann normales RPC macht, aber der Caller (der den Thread erstellt hat) kann sofort danach (Threaderstellung) weitermachen.
Kann man so machen aber ist natürlich zusätzlicher Overhead. Wenn man schon beim Callee einen neuen Thread erzeugt ist es IMHO Unsinn auch noch beim Caller einen neuen Thread zu erzeugen der eigentlich nur dazu dient untätig zu blockieren bis der Callee fertig ist.
(das ich nicht wüsste was eine Anwendung weiter machen sollte, wenn sie noch keine Daten hat, ist erstmal egal)
Mit asynchronem I/O kann man z.B. einen HTTP-Server als Single-Thread-Applikation bauen, dieser eine Thread managed dann alle aktiven Verbindungen. Auf diese Art spart man sich ne Menge Kontext-Switches. Dafür benötigt man natürlich entsprechende (komplexe) Mechanismen mit denen man erkennen kann bei welcher der vielen Verbindungen als nächstes Daten nachgeschoben werden können. Auch wenn man jede Verbindung mit einem eigenen Thread behandelt kann asynchrones I/O helfen, indem man z.B. Double-Buffering betreibt, während die Daten aus dem einen Buffer per TCP verschickt werden können in den anderen Buffer die nächsten Daten eingelesen werden (falls die Daten z.B. von PHP kommen ist es sicher von Vorteil wenn zumindest das Senden per TCP bequem im Hintergrund läuft) und wenn beides fertig ist wird getauscht.
was ändert dieser Callback, dass die Anwendung miteinmal die Daten, die jetzt vorhanden sind, nutzt?
Ja, genau darum gehts.
Wird der Code der die Daten verarbeitet direkt in dem Callback ausgeführt?
Kann man machen muss man aber nicht, das hängt davon ab wie man sein Programm entwirft. In dem Beispiel mit dem Double-Buffering (mit asynchronem File-read und asynchronem TCP-write) würde ich im Call-Back-Handler nur jeweils ein Flag setzen und den eigentlichen Arbeits-Thread aufwecken (falls das andere Flag auch gesetzt ist). Man kann aber auch die Daten gleich verarbeiten und gegebenenfalls den nächsten asynchronen IPC-Vorgang anstoßen, falls dann der Call-Back-Handler fertig ist bevor der nächste IPC-Vorgang beendet wird (und auch wieder einen Call-Back-Handler anstößt) kann es sogar sein das für diese konkrete Aufgabe gar kein Thread in dem Programm existiert (nicht mal ein blockierter).
Wird für den Callback der laufende Thread unterbrochen (wenn ja, welcher Thread, bei Multithreading) oder wird dafür ein neuer erstellt?
Das ist auch wieder davon abhängig wie Du das implementierst. In meinem System soll ein neuer Thread injiziert werden (genauso wie der PopUp-Thread beim Callee).
Denn ich gehe davon aus, dass das meiste was per IPC kommuniziert wird unter 4kb liegt.
Davon bin ich nicht unbedingt überzeugt, aber ich schätze zumindest für Dinge wie stdin/stdout/stderr dürfte das zutreffen.
Soweit Theorie. Ein Bsp. fällt mir ein wo mapping schneller wäre, anstatt die Daten die man per read() anfordert ständig in einzelne Msgs zu kopieren, könnte man immer eine oder zwei Pages der Datei per Mapping in den Prozess gemappt haben ....
Tolle Idee, aber dann mach doch gleich richtiges Memory-Mapped-File-I/O.
Grüße
Erik