IPC: Gemeinsamer Speicher
Veranschaulicht, wie Bilddaten mithilfe des IPC-Mechanismus „Shared Memory“ zwischen verschiedenen Prozessen ausgetauscht werden können.
Das Beispiel „Shared Memory“ zeigt, wie man mithilfe der Klasse „ QSharedMemory “ die Interprozesskommunikation über Shared Memory implementiert. Um das Beispiel zu erstellen, führen Sie „make“ aus. Um das Beispiel auszuführen, starten Sie zwei Instanzen der ausführbaren Datei. Die Funktion „main()“ erstellt ein „ application “ und eine Instanz der „Dialog“-Klasse unseres Beispiels. Das Dialogfeld wird angezeigt, und anschließend wird die Steuerung auf übliche Weise an die Anwendung übergeben.
int main(int argc, char *argv[])
{
QApplication application(argc, argv);
Dialog dialog;
dialog.show();
return application.exec();
}Es werden zwei Instanzen der Klasse „Dialog“ angezeigt.

Die Klasse „Dialog“ erbt v QDialog. Sie kapseln die Benutzeroberfläche und eine Instanz von „ QSharedMemory “. Außerdem verfügt sie über zwei öffentliche Slots, „loadFromFile()“ und „loadFromMemory()“, die den beiden Schaltflächen im Dialog entsprechen.
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
public slots:
void loadFromFile();
void loadFromMemory();
private:
void detach();
private:
Ui::Dialog ui;
QSharedMemory sharedMemory;
};Der Konstruktor erstellt die Widgets der Benutzeroberfläche und verbindet das Signal „clicked()“ jeder Schaltfläche mit der entsprechenden Slot-Funktion.
Dialog::Dialog(QWidget *parent)
: QDialog(parent), sharedMemory(QNativeIpcKey(u"QSharedMemoryExample"_s))
{
ui.setupUi(this);
connect(ui.loadFromFileButton, &QPushButton::clicked,
this, &Dialog::loadFromFile);
connect(ui.loadFromSharedMemoryButton, &QPushButton::clicked,
this, &Dialog::loadFromMemory);
setWindowTitle(tr("SharedMemory Example"));
}Beachten Sie, dass „QSharedMemoryExample“ als Schlüssel an den Konstruktor von ` QSharedMemory() ` übergeben wird. Dieser wird vom System als Kennung des zugrunde liegenden Shared-Memory-Segments verwendet.
Klicken Sie auf die Schaltfläche „ Load Image From File... “ in einem der Dialoge. Der Slot `loadFromFile()` wird aufgerufen. Zunächst wird geprüft, ob bereits ein Shared-Memory-Segment an den Prozess angehängt ist. Ist dies der Fall, wird dieses Segment vom Prozess getrennt, sodass sichergestellt ist, dass das Beispiel korrekt gestartet wird.
void Dialog::loadFromFile()
{
if (sharedMemory.isAttached())
detach();
ui.label->setText(tr("Select an image file"));
QString fileName = QFileDialog::getOpenFileName(0, QString(), QString(),
tr("Images (*.png *.xpm *.jpg)"));
QImage image;
if (!image.load(fileName)) {
ui.label->setText(tr("Selected file is not an image, please select another."));
return;
}
ui.label->setPixmap(QPixmap::fromImage(image));Anschließend wird der Benutzer aufgefordert, mithilfe von ` QFileDialog::getOpenFileName()` eine Bilddatei auszuwählen. Die ausgewählte Datei wird in ein ` QImage` geladen. Mithilfe von ` QImage ` können wir sicherstellen, dass es sich bei der ausgewählten Datei um ein gültiges Bild handelt, und das Bild sofort mithilfe von `setPixmap()` im Dialog anzeigen.
Als Nächstes wird das Bild mithilfe von ` QDataStream` in ein ` QBuffer ` gestreamt. Dadurch erhalten wir die Größe, die wir anschließend verwenden, um unser Shared-Memory-Segment mit ` create()` zu initialisieren. Das Erstellen eines Shared-Memory-Segments führt automatisch dazu, dass das Segment dem Prozess zu attaches t wird. Mit ` QBuffer ` erhalten wir hier einen Zeiger auf die Bilddaten, den wir dann verwenden, um mit `memcopy()` Daten aus dem ` QBuffer ` in das Shared-Memory-Segment zu kopieren.
// load into shared memory
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
QDataStream out(&buffer);
out << image;
int size = buffer.size();
if (!sharedMemory.create(size)) {
if (sharedMemory.error() == QSharedMemory::AlreadyExists) {
sharedMemory.attach();
} else {
ui.label->setText(tr("Unable to create or attach to shared memory segment: %1")
.arg(sharedMemory.errorString()));
return;
}
}
sharedMemory.lock();
char *to = (char*)sharedMemory.data();
const char *from = buffer.data().data();
memcpy(to, from, qMin(sharedMemory.size(), size));
sharedMemory.unlock();
}Beachten Sie, dass wir das gemeinsam genutzte Speichersegment vor dem Kopieren mit ` lock()` sperren und es unmittelbar nach dem Kopieren erneut mit ` unlock()` sperren. Dies stellt sicher, dass wir exklusiven Zugriff auf das gemeinsam genutzte Speichersegment haben, um unseren `memcopy()`-Vorgang durchzuführen. Falls ein anderer Prozess die Sperre für das Segment hält, wird unser Prozess so lange blockiert, bis die Sperre verfügbar wird.
Beachten Sie außerdem, dass die Funktion nach dem memcopy() und unlock() kein „ detach()“ vom gemeinsam genutzten Speichersegment durchführt. Erinnern Sie sich daran, dass das Segment vom Betriebssystem freigegeben wird, sobald sich der letzte Prozess von einem gemeinsam genutzten Speichersegment trennt. Da dieser Prozess derzeit der einzige ist, der mit dem gemeinsamen Speichersegment verbunden ist, würde das Segment zerstört werden, bevor wir zum nächsten Schritt gelangen, falls sich `loadFromFile()` vom gemeinsamen Speichersegment trennen würde.
Wenn die Funktion zurückkehrt und die von Ihnen ausgewählte Datei „qt.png“ war, sieht Ihr erster Dialog wie folgt aus.

Klicken Sie im zweiten Dialogfeld auf die Schaltfläche „ Display Image From Shared Memory “. Der Slot „loadFromMemory()“ wird aufgerufen. Zunächst wird der Prozess über „ attaches “ mit demselben gemeinsam genutzten Speichersegment verbunden, das vom ersten Prozess erstellt wurde. Anschließend wird das Segment über „ locks “ für den exklusiven Zugriff gesperrt und ein „ QBuffer “ mit den Bilddaten im gemeinsam genutzten Speichersegment verknüpft. Danach werden die Daten in ein „ QImage “ gestreamt und das Segment wird über „ unlocks “ freigegeben.
void Dialog::loadFromMemory()
{
if (!sharedMemory.attach()) {
ui.label->setText(tr("Unable to attach to shared memory segment.\n" \
"Load an image first."));
return;
}
QBuffer buffer;
QDataStream in(&buffer);
QImage image;
sharedMemory.lock();
buffer.setData((char*)sharedMemory.constData(), sharedMemory.size());
buffer.open(QBuffer::ReadOnly);
in >> image;
sharedMemory.unlock();
sharedMemory.detach();
ui.label->setPixmap(QPixmap::fromImage(image));
}In diesem Fall führt die Funktion „ detach()“ für das Segment aus, da wir dessen Nutzung nun effektiv beendet haben. Abschließend wird das „ QImage “ angezeigt. Zu diesem Zeitpunkt sollten beide Dialoge dasselbe Bild anzeigen. Wenn Sie den ersten Dialog schließen, ruft der Destruktor des Dialogs den Destruktor von „ QSharedMemory “ auf, der die Verbindung zum gemeinsam genutzten Speichersegment trennt. Da dies der letzte Prozess ist, der vom Segment getrennt wird, gibt das Betriebssystem nun den gemeinsam genutzten Speicher frei.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.