IPC : Mémoire partagée
Cet exemple montre comment partager des données d'image entre différents processus à l'aide du mécanisme IPC de mémoire partagée.
L'exemple « Mémoire partagée » montre comment utiliser la classe ` QSharedMemory ` pour implémenter la communication interprocessus à l'aide de la mémoire partagée. Pour compiler l'exemple, exécutez la commande `make`. Pour exécuter l'exemple, lancez deux instances de l'exécutable. La fonction `main()` crée une instance de ` application ` et une instance de la classe `Dialog` de notre exemple. La boîte de dialogue s’affiche, puis le contrôle est transféré à l’application de manière standard.
int main(int argc, char *argv[])
{
QApplication application(argc, argv);
Dialog dialog;
dialog.show();
return application.exec();
}Deux instances de la classe `Dialog` s’affichent.

La classe `Dialog` hérite de ` QDialog`. Elle encapsule l'interface utilisateur et une instance de ` QSharedMemory`. Elle dispose également de deux slots publics, `loadFromFile()` et `loadFromMemory()`, qui correspondent aux deux boutons de la boîte de dialogue.
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;
};Le constructeur crée les widgets de l’interface utilisateur et relie le signal clicked() de chaque bouton à la fonction de slot correspondante.
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"));
}Notez que « QSharedMemoryExample » est passé au constructeur de ` QSharedMemory() ` pour servir de clé. Cette clé sera utilisée par le système comme identifiant du segment de mémoire partagée sous-jacent.
Cliquez sur le bouton « Load Image From File... » de l’une des boîtes de dialogue. Le slot loadFromFile() est appelé. Il vérifie d’abord si un segment de mémoire partagée est déjà associé au processus. Si c’est le cas, ce segment est dissocié du processus, ce qui nous permet de nous assurer que l’exemple démarre correctement.
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));L’utilisateur est ensuite invité à sélectionner un fichier image à l’aide de ` QFileDialog::getOpenFileName()`. Le fichier sélectionné est chargé dans un ` QImage`. L’utilisation d’un ` QImage ` nous permet de nous assurer que le fichier sélectionné est une image valide, et nous permet également d’afficher immédiatement l’image dans la boîte de dialogue à l’aide de `setPixmap()`.
Ensuite, l’image est transmise en continu vers un ` QBuffer ` à l’aide de ` QDataStream`. Cela nous fournit la taille, que nous utilisons ensuite pour appeler ` create()` sur notre segment de mémoire partagée. La création d’un segment de mémoire partagée attribue automatiquement le segment au processus via ` attaches `. L’utilisation de ` QBuffer ` nous permet ici d’obtenir un pointeur vers les données de l’image, que nous utilisons ensuite pour effectuer une copie (`memcopy()`) depuis le ` QBuffer ` vers le segment de mémoire partagée.
// 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();
}Notez que nous appelons ` lock()` sur le segment de mémoire partagée avant d’y effectuer la copie, puis que nous appelons à nouveau ` unlock()` immédiatement après la copie. Cela garantit que nous disposons d’un accès exclusif au segment de mémoire partagée pour effectuer notre `memcopy()`. Si un autre processus détient le verrou du segment, notre processus se bloquera jusqu’à ce que le verrou soit disponible.
Notez également que la fonction n’utilise pas la fonction ` detach()` pour se détacher du segment de mémoire partagée après les appels à `memcopy()` et `unlock()`. Rappelons que lorsqu’un processus se détache d’un segment de mémoire partagée, ce segment est libéré par le système d’exploitation. Comme ce processus est le seul à être attaché au segment de mémoire partagée pour le moment, si la fonction `loadFromFile()` se détachait du segment de mémoire partagée, celui-ci serait détruit avant que nous passions à l’étape suivante.
Lorsque la fonction revient, si le fichier que vous avez sélectionné était qt.png, votre première boîte de dialogue se présente comme suit.

Dans la deuxième boîte de dialogue, cliquez sur le bouton « Display Image From Shared Memory ». Le slot `loadFromMemory()` est appelé. Il commence par « attaches » le processus au même segment de mémoire partagée que celui créé par le premier processus. Ensuite, il « locks » le segment pour un accès exclusif et lie un « QBuffer » aux données d’image contenues dans le segment de mémoire partagée. Il transfère ensuite les données vers un « QImage » et « unlocks » le segment.
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));
}Dans ce cas, la fonction appelle ` detach()` à partir du segment, car nous avons désormais effectivement fini de l’utiliser. Enfin, l’ QImage e s’affiche. À ce stade, les deux boîtes de dialogue devraient afficher la même image. Lorsque vous fermez la première boîte de dialogue, le destructeur de la boîte de dialogue appelle le destructeur de l’ QSharedMemory, qui se détache du segment de mémoire partagée. Comme il s’agit du dernier processus à se détacher du segment, le système d’exploitation libère alors la mémoire partagée.
© 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.