C - shared memory - dynamisches Array in shared struct

9

Ich versuche, eine Struktur wie diese zu teilen Beispiel:

%Vor%

zwischen Prozessen, ist das Problem, dass, wenn ich "a" mit einem malloc initialisiere, es privat zu dem Haufen des Prozesses wird, der das tut (oder mindestens ich denke, dass das ist, was passiert). Gibt es eine Möglichkeit, einen gemeinsamen Speicher (mit Shmget, Shmat) mit dieser Struktur zu erstellen, die funktioniert?

BEARBEITEN: Ich arbeite an Linux.
EDIT: Ich habe einen Prozess, der den Puffer wie folgt initialisiert:

%Vor%

Der andere Prozess hängt sich folgendermaßen an den gemeinsamen Speicher an:

%Vor%

und später erhalten ein Element von einem, in diesem Fall das in Position 1

%Vor%     
ChiP 28.01.2013, 08:50
quelle

5 Antworten

2

Der Speicher, den Sie einem Zeiger mit malloc() zuweisen, ist für diesen Prozess privat. Wenn Sie also versuchen, auf den Zeiger in einem anderen Prozess (außer dem Prozess, der ihn verteilte) zuzugreifen, werden Sie wahrscheinlich auf eine ungültige Speicherseite oder eine Speicherseite zugreifen, die in einem anderen Prozessadressraum zugeordnet ist. Sie erhalten also wahrscheinlich einen Segfault.

Wenn Sie den gemeinsamen Speicher verwenden, müssen Sie sicherstellen, dass alle Daten, die Sie anderen Prozessen zur Verfügung stellen möchten, sich im Shared-Memory-Segment und nicht in privaten Speichersegmenten des Prozesses befinden.

Sie könnten versuchen, die Daten an einem bestimmten Offset im Speichersegment zu lassen, das zur Kompilierungszeit konkret definiert oder in einem Feld an einer bekannten Position im Shared Memory-Segment platziert werden kann.

ZB: Wenn Sie dies tun

char *mem = shmat(shmid2, (void*)0, 0);

%Vor%

Eine andere Möglichkeit wäre, einen Puffer fester Größe zu haben, um die Information unter Verwendung des Shared-Memory-Ansatzes zu übergeben, anstatt den dynamisch zugewiesenen Zeiger zu verwenden.

Hoffe, das hilft.

    
askmish 28.01.2013 09:53
quelle
2

Um den Inhalt, auf den das Feld int *a zeigt, zu teilen, müssen Sie zuerst den gesamten Speicher kopieren, der damit zusammenhängt. Daher benötigen Sie einen gemeinsamen Speicher, der mindestens size_t shm_size = sizeof(struct ex) + get_the_length_of_your_ex(); enthalten kann.

Von jetzt an, seit Sie Shmget und Shmat erwähnt haben, nehme ich an, dass Sie ein Linux-System betreiben.
Der erste Schritt ist die Shared Memory-Segmenterstellung . Es wäre gut, wenn Sie eine Obergrenze für die Größe des int *a -Inhalts festlegen können. Auf diese Weise müssen Sie das Shared Memory-Segment nicht immer neu erstellen / löschen. Aber wenn Sie dies tun, ein zusätzlicher Overhead, um anzugeben, wie lange die tatsächlichen Daten benötigt werden. Ich gehe davon aus, dass ein einfacher size_t den Zweck für diesen Zweck erfüllen wird.

Nachdem Sie Ihr Segment erstellt haben, müssen Sie die Daten dann korrekt festlegen, damit es das enthält, was Sie möchten. Beachten Sie, dass die physikalische Adresse des Speichersegments immer gleich ist, wenn Sie shmat aufrufen, erhalten Sie virtuelle Zeiger, die nur in dem Prozess verwendet werden können, der shmat aufgerufen hat. Der folgende Beispielcode sollte Ihnen einige Tricks geben.

%Vor%

Entschuldigen Sie meine Faulheit, es wäre platzoptimiert, den Wert des int *a -Zeigers der struct ex gar nicht zu kopieren, da er im Shared Memory nicht benutzt wird, aber ich habe es verschont Ich habe extra Code, um das zu handhaben (und einige Zeigerüberprüfungen wie die Integrität der Argumente von p_ex).

Aber wenn Sie fertig sind, müssen Sie einen Weg finden, die shm ID zwischen Ihren Prozessen zu teilen. Dies könnte unter Verwendung von Sockets, Pipes ... oder mit ftok mit der gleichen Eingabe erfolgen.

    
Rerito 28.01.2013 09:56
quelle
1

Arbeiten Sie in Windows oder Linux? In jedem Fall benötigen Sie eine Memory-Mapped-Datei . Dokumentation mit Codebeispielen hier,

Ссылка Ссылка

    
jpmuc 28.01.2013 09:01
quelle
1

Sie müssen shared memory / memory mapped files verwenden / was auch immer Ihr Betriebssystem Ihnen bietet. Im Allgemeinen ist IPC und das Teilen von Speicher zwischen Prozessen ziemlich vom Betriebssystem abhängig, insbesondere in Low-Level-Sprachen wie C (höhere Programmiersprachen haben normalerweise Bibliotheken dafür - beispielsweise unterstützt sogar C ++ Boost mit boost). Wenn Sie Linux verwenden, verwende ich normalerweise shmat für kleine Mengen und mmap ( Ссылка ) für größere Mengen. Auf Win32 gibt es viele Ansätze; die eine, die ich bevorzuge, ist in der Regel mit Seiten-Datei gesichert Speicher-Mapped-Dateien ( Ссылка )

Außerdem müssen Sie darauf achten, wo Sie diesen Mechanismus in Ihren Datenstrukturen verwenden: Wie in den Kommentaren erwähnt, ist der Zeiger, den Sie in Ihrem "Quellen" -Prozess haben, im "Ziel" -Prozess ohne Vorkehrungen ungültig. und muss ersetzt / angepasst werden (IIRC, Zeiger, die von mmap kommen, sind bereits OK (gemappt); zumindest unter Windows-Zeigern, die du aus MapViewOfFile bekommst, sind OK).

BEARBEITEN: aus Ihrem bearbeiteten Beispiel: Was du hier machst:

%Vor%

(anderer Prozess)

%Vor%

ist korrekt, aber Sie müssen es für jeden Zeiger tun, den Sie haben, nicht nur für den "Haupt" -Zeiger auf die Struktur. Z.B. Sie müssen tun:

%Vor%

anstatt das Array mit malloc zu erstellen. Dann müssen Sie für den Zeiger auch shmget / shmat ausführen. Aus diesem Grund habe ich in den Kommentaren gesagt, dass ich die Strukturen normalerweise lieber packe: Ich muss also nicht für jeden Zeiger den Aufwand auf diese Operationen anwenden.

    
Lorenzo Dematté 28.01.2013 09:03
quelle
0

Konvertiere die Struktur:

%Vor%

und dann im übergeordneten Prozess:

%Vor%

sollte es funktionieren.

Im Allgemeinen ist es schwierig, mit dynamischen Arrays innerhalb von Strukturen in c zu arbeiten, aber auf diese Weise können Sie den richtigen Speicher zuweisen (dies funktioniert auch in malloc: Wie ein dynamisches Array INSIDE eine Struktur in C enthalten? )

    
Pantokratoras 7 04.01.2017 18:59
quelle

Tags und Links