C IPC - Pipes - FIFOs - oder was besseres?

hell-student

Lieutenant
Registriert
Nov. 2007
Beiträge
671
Hallo Zusammen,

Ich bin momentan auf der Suche nach einer Möglichkeit zwischen 2 Prozessen Daten auszutauschen. Mein Problem ist, dass Pipes ja nur bei geforkten Prozessesen (Parent/Child) funktionieren. Ein FIFO habe ich gerade implementiert und das funktioniert auch soweit, jedoch würde ich gerne nicht blockend Daten austauschen.

Mein Szenario:

Programm A rechnet was und wenn Programm B Daten in den FIFO, shared Mem oder ähnliches schaufelt, soll A aufhören, da die Berechnung auf alten Daten arbeitet und somit verworfen werden kann. Schon lange nichts mehr mit C gemacht, daher frage ich mich, ob es überhaupt geht, während dem Berechnen abzubrechen OHNE zu pollen ob Daten da sind. Quasi ein Handler für das Signal, dass neue Daten da sind. Jedoch frage ich mich, ob ich dann einfach so die Datenstrukturen/Speicher etc alles wieder so einfach freigeben werden.
 
wenn du mit fifo "named pipes"meinst, dann gehen die auch nicht blockierend.

darüber hinaus gibt es noch shared memory als alternative und message queueing.
 
Ich würde nen Shared Memory anlegen und dann Messages senden, bzw. kannst du in Windows auch Events (Semaphore) verwenden. Oder du pollst im Prozess A einfach dauernt eine Größe im Shared Memory ab, wobei du hier natürlich auch mit ner Semaphore etc. den Zugriff schützen solltest.
 
entschuldige. hab mal den unteren teil desTE-posts genauer gelesen. bei dem szenario sind named pipes + signals genau was du suchtst. du bekommst ein event (singal), wenn was in der pipe ansteht.
 
Du musst eben aufpassen dass alle Daten auch wirklich im Shared Memory bzw. in der Pipe landen. Z.b. statische Strings sind schon problematisch da sie im Stack oder Heap des jeweiligen Prozesses liegen, du jeweils meist nur den Zeiger kopierst.

Hilfreich ist sowas wie eine Daten-Serialisierung in die Pipe bzw. auf den SharedMem.
 
Danke für eure Antworten.

Ich bin jedoch nach langem Suchen nicht schlauer geworden. Habe einiges über IPC gelesen und mir auch ein nettes Buch dazu geholt. Mein Problem ist, dass ich gerne eine asynchrone (also blockierungsfreie) Übertragung hätte. Zu Message Queues hab ich gelesen, dass diese sehr langsam seien sollen im Vergleich zu FIFOs bzw. SharedMem.
 
Kauf das Buch WIN32 Programmierung von Charles Petzold, mein Tip ! Ich wüsste gar nicht was an Events langsam sein sollte, wenn Du die Threads damit synchronisierst...Wenn der lahmende Thread die Knochen gebrochen hat, dann schickt der halt noch ein Event, lahme hier rum... Das Event macht den nicht langsamer, die schnelleren Threads wissen dann, Kollege lahmt rum...den nehmen wir mit und wenn er stirbt, dann beerdigen wir ihn nich, debug Message, Fred ist gestorben.
 
Zuletzt bearbeitet:
Na im Prinzip steckt schon ein Quant Wahrheit dahinter: Alle API Funktionen die den Kernel ansprechen (i.d.R. alles was ein HANDLE hat) brauchen etwas länger. Man sollte sie nicht Millarden-Mal in einer zeitkritischen Schleife aufrufen. Dann lieber nen Puffer bauen und größere Pakete in einem Rutsch senden.
 
Also am schnellsten müsste SharedMem sein, vor allem, wenn die Hashmap nicht ganz klein ist.
In Verbindung mit einer Semaphore hast du da deine Singalisierung.

Bei shared mem musst du aufpassen, dass halt alles
1. Zeigerunabhängig ist und
2. im shared mem liegt.
Was dich dann wahrscheinlich dazu zwingt, deine Hashmap selber zu schreiben.
Oder aber du findest eine "Serialisierung" der Hashmap, die schnell ist. Ala
Hashmapgröße
1. Hash
Anzahl der Elemente
1. Element ... n. Element
2. Hash
...
m-ter Hash+Elemente

Dann fällt die Pointerproblematik weg und du kannst zwei Strategien fahren:
1. Der Quellprozess kopiert nach dem Signalisieren und der Freigabe durch den 2. Prozess die Hashmap in den Shared mem und signalisiert das dem 2. Prozess
2. Der Verarbeitungsprozess kopiert immer die Hashmap sofort wieder raus und der Quellprozess schreibt direkt in den Shared mem die Hashmap rein.
Ich würde die erste Methode nehmen, da du dir beim Einfügen von Elementen keine Sorge machen musst.
 
beziehst dich auf mich? :)

habe für mich persönlich dieses thema verworfen. boost bietet das ablegen von STL objekten in den shared-ram ohne sie kopieren zu müssen, aber ich selbst arbeite auf hashmaps von QT, die ich nicht an der stelle an boost koppeln kann.

die QT hashmap ist dabei über 500MB groß und was einfügen und wiederfinden von elementen angeht allen bisherigen hashmaps voraus. das manko bei der QT hashmap ist die zeit beim abbau dieser. die datenstruktur von QT perforiert den heap beim anlegen der elemente, beim abbau defragmentiert sie ihn aber immer wieder.. so das es ca so aussieht, dass ich in 5 sekunden eine 500MB hashmap aufbauen kann, aber beim zerstören 3minuten brauche. die hashmap von STL suckt schon bei 10.000 elementen ab, die von google braucht genau so lange zum aufbauen wie beim abbauen.

nun dachte ich die QT hashmap in einen anderen prozess zu packen und sie via interprocess aufzupumpen und auf sie zuzugreifen - und wenn ich sie wieder loshaben will, einfach den entsprechenden prozess zu terminieren. aber nöö :)

die letzte möglichkeit wäre dll-injection, zu dem zb microsoft detours bereithält. zu ansätzen dieser gruppe zählt zb fraps, der sich via code-injection zwischen directx oder opengl einklingt und die entsprechenden daten direkt abgreift oder manipuliert.
 
Zuletzt bearbeitet:
Eig. auf den TE.
Zu boost: Der TE möchte doch in C programmieren.

Also ich hab ma 3.7 Mio. Elemente (a 200 Byte) in ne normale Map reingetan, war ganz performant^^.
Einmal mit 77 Mio. Elemente war die Map allein schon 2,9 GB groß (multimap<int,int>).

Die Idee, ne Hashmap auszulagern ist gut, aber dann nehm doch einfach die sharedmem Variante und gebe den Speicher wieder frei. Sonst geht das auch per STL, nehm ein Custom allocator, was aber ein gefrickel wird...

Was du mit detours machen willst, ist mir schleierhaft, da die Daten zu kopieren grad das Problem sein sollte, oder versteh ich dich da grad falsch?
 
mit detours kannst folgendes machen: nimmst eine beliebige klasse (zb hashmap) und stellst ihre methoden zum dllexport bereit und ziehst diese dll in einem prozess B an.

im prozess A nutzt du detours um im prozess B die von der dll exportierten methoden aufzurufen - und das komplett auf kosten von prozess B.

hmm, custom allocator - ich prüfe das mal, dank dir.
 
Danke euch für die Antworten. Leider bin ich noch nicht weitergekommen.

Kann ich FIFOs (named pipe) so benutzen wie message queues?

Ich hab ein Programm das in eine Message Queue reinschreibt und sich beendet. Ein weiteres Programm kann danach den geschriebenen Wert lesen und printen.

Mit Fifos bekomme ich das nicht hin, also ohne Handshake. Geht das überhaupt, das der Writer beendet ist, bevor der Reader liest? Bei mir liest der Reader nichts mehr, weil wohl der Writer abbricht, wenn kein Reader da ist.
thx
 
überleg doch mal - was würde passieren, wenn jeder prozess etwas im RAM ablegen und nach dem beenden liegenlassen dürfte; aus der perspektive eines BS-entwicklers.
 
Ok verstanden.

Ich habe aber momentan mit FIFOs ein weiteres Problem. Ich habe mehrere Writer und daher wird die Nachricht, die ich übermitteln will zwar nicht interleaved, aber es gibt ja keine Nachrichten bzw Nachrichtgrenzen. Eher ein Stream. Daher habe ich das Problem, dass wenn mehrere Writer gleichzeitig auf die FIFO schreiben sowas rauskommt:

1 Writer schreibt immer Hallo

Wenn 3 Writer immer wieder schreiben
HalloHalloHallo
Hallo
HalloHallo
...

Also mein Problem besteht dann auf der Reader-Seite. Wie kann ich nun am effizientesten ermitteln was da ankommt. Manchmal sind auch andere Zeichen in der Pipe. Mit Message Queues habe ich halt einfach getrennte Nachrichten, also kann dort soetwas nicht auftreten.
 
Zurück
Oben