2009-03-30 5 views
2

Ich versuche derzeit, einige Interprozesskommunikation unter Verwendung des Windows CreateFileMapping Mechanismus zu implementieren. Ich weiß, dass ich zuerst ein File-Mapping-Objekt mit CreateFileMapping erstellen und dann einen Zeiger auf die tatsächlichen Daten mit MapViewOfFile erstellen muss. Im Beispiel werden dann mithilfe von CopyMemory Daten in die Mapdatei eingefügt.Shared Memory unter Windows verwenden. Wie man verschiedene Daten übergibt

In meiner Anwendung habe ich einen Bildpuffer (1 MB groß), die ich an einen anderen Prozess senden möchte. Jetzt frage ich einen Zeiger auf das Bild und kopiere dann den gesamten Bildpuffer in die Mapdatei. Aber ich frage mich, ob das wirklich notwendig ist. Ist es nicht möglich, nur einen tatsächlichen Zeiger in den gemeinsamen Speicher zu kopieren, der auf die Bildpufferdaten zeigt? Ich habe es ein bisschen versucht, aber es ist mir nicht gelungen.

+0

Murali Devi bietet [funktionierenden Beispielcode für Shared Memory in Windows] (http://comsci.liu.edu/~murali/win32/SharedMemory.htm). Sein Beispiel verwendet Speicher, keine tatsächliche Datei, also ist es genau der Fall, den Sie beschreiben. –

Antwort

8

Verschiedene Prozesse haben unterschiedliche Adressräume. Wenn Sie einen gültigen Zeiger in einem Prozess an einen anderen Prozess übergeben, wird er im zweiten Prozess wahrscheinlich auf zufällige Daten verweisen. Sie müssen also alle Daten kopieren.

+1

Nicht immer wahr. – RandomNickName42

+2

@ RandomNickName42: Mit Ausnahme von Shared Memory gilt dies generell für alle gängigen Betriebssysteme. – Zifre

0

Sie können das Marshalling von Zeigern verwenden.

8

I stark empfehlen, dass Sie Boost::interprocess verwenden. Es hat viele Extras, um diese Art von Sachen zu verwalten & enthält sogar einige spezielle Windows-only-Funktionen für den Fall, dass Sie mit anderen Prozessen interagieren müssen, die bestimmte Win32-Funktionen verwenden.

Die wichtigste Sache ist die Verwendung von offset pointers anstelle von regulären Zeigern. Versatzzeiger sind im Grunde relative Zeiger (sie speichern die Differenz zwischen der Position des Zeigers und der Stelle, auf die der Zeiger zeigt). Dies bedeutet, dass selbst wenn die beiden Zeiger auf unterschiedliche Adressräume abgebildet werden, solange die Zuordnungen in der Struktur identisch sind, alles in Ordnung ist.

Ich habe alle Arten von komplizierten Datenstrukturen mit Offset-Smart-Zeigern verwendet und es funktionierte wie ein Charme.

+0

Dies sind sogenannte "based pointer", die sehr benötigt werden, wenn 64-Bit-Zeiger überall sind. – RandomNickName42

0

Wenn es möglich ist, wäre es am besten, wenn die Bilddaten direkt in den gemeinsamen Speicherbereich geladen/erzeugt werden. Dies eliminiert die Speicherkopie und bringt sie direkt dorthin, wo sie benötigt wird. Wenn es fertig ist, können Sie den anderen Prozess signalisieren und ihm den Offset in Ihren Shared Memory geben, wo die Daten beginnen.

2

Sie CAN erhalten gemeinsamen Speicher, um die gleiche Adresse über 2 Prozesse für Windows zu verwenden. Es ist mit mehreren Techniken erreichbar.

Unter Verwendung von MapViewOfFileEx, hier ist die wichtige Kompetenz von MSDN.

Wenn eine vorgeschlagene Mapping-Adresse geliefert wird, wird die Datei auf der angegebene Adresse zugeordnet (abgerundet auf die nächste 64K-Grenze), wenn es genug Adressraum an der angegebenen Adresse ist. Wenn der Adressraum nicht ausreicht, schlägt die Funktion fehl.

Typischerweise wird die vorgeschlagene Adresse ist verwendet, um festzulegen, dass eine Datei an derselben Adresse in mehreren Prozesse abgebildet werden soll. Dies erfordert, dass der Bereich Adressraum in allen beteiligten Prozessen verfügbar ist.Kein anderer Speicher Zuordnung kann in der Region, die für die Zuordnung verwendet wird, einschließlich der Verwendung der VirtualAlloc oder VirtualAllocEx-Funktion zum Reservieren Speicher stattfinden.

Wenn die Parameter lpBaseAddress eine Basis spezifiziert versetzt, die Funktion erfolgreich ist, wenn der angegebene Speicher Bereich, der nicht bereits von dem Aufruf Prozess. Das System stellt nicht sicher, dass die gleiche Speicherregion für die Speicherabbilddatei in anderen 32-Bit-Prozessen verfügbar ist.

Eine andere verwandte Technik besteht darin, eine DLL mit einem Abschnitt zu verwenden, der als Read + Write + Shared markiert ist. In diesem Fall führt das Betriebssystem den MapViewOfFileEx-Aufruf für Sie und für jeden anderen Prozess, der die DLL lädt, ziemlich aus.

Möglicherweise müssen Sie Ihre DLL zu einer festen Ladeadresse markieren, die nicht umsetzbar ist usw. Natürlich.

3

Shared Memory bedeutet nicht das Senden und Empfangen von Daten. Es ist ein Speicher für die Anzahl der Prozesse ohne Verletzung erstellt. Dafür müssen Sie einige Mechanismen wie Sperren befolgen, damit die Daten nicht beschädigt werden.

Im Verfahren 1:

CreateFileMapping(): Es wird den Shared-Memory-Block, mit dem in der letzten Parametern angegebenen Namen erstellen, wenn es nicht bereits vorhanden ist, und gibt einen Handle (Sie kann es einen Zeiger nennen) zurück, Falls erfolgreich.

MapViewOfFile(): Es bildet (enthält) diesen freigegebenen Block im Prozess Adressraum und gibt ein Handle (wieder kann man einen Zeiger sagen).

Mit diesem von MapViewOfFile() zurückgegebenen Zeiger können Sie nur auf diesen freigegebenen Block zugreifen.

Im Verfahren 2:

OpenFileMapping(): Wenn der Shared-Memory-Block erfolgreich durch CreateFileMapping() erstellt wird, können Sie es mit dem gleichen Namen verwenden können (Name verwendet, um den gemeinsamen Speicherblock).

UnmapViewOfFile(): Es wird die Zuordnung aufgehoben (Sie können den freigegebenen Speicherblock aus diesem Prozessadressraum entfernen). Wenn Sie mit dem gemeinsamen Speicher fertig sind (d. H. Zugriff, Änderung usw.), rufen Sie diese Funktion auf.

Closehandle(): schließlich den freigegebenen Speicherblock vom Prozess trennen, rufen Sie dies mit Argument, Handle von OpenFileMapping() oder CreateFileMapping() zurückgegeben.

Obwohl diese Funktionen einfach aussehen, ist das Verhalten schwierig, wenn die Flags nicht richtig ausgewählt sind. Wenn Sie Shared Memory lesen oder schreiben möchten, geben Sie PAGE_EXECUTE_READWRITE in CreateFileMapping() an.

Wenn Sie nach dem erfolgreichen Erstellen auf den gemeinsam genutzten Speicher zugreifen möchten, verwenden Sie FILE_MAP_ALL_ACCESS in MapViewOfFile().

Es ist besser zu spezifizieren FALSE (erben Sie nicht Handle von Elternprozess) in OpenFileMapping(), da es Verwirrung vermeiden wird.