IPC: 공유 메모리
공유 메모리 IPC 메커니즘을 사용하여 서로 다른 프로세스 간에 이미지 데이터를 공유하는 방법을 보여줍니다.
공유 메모리 예제는 ` QSharedMemory ` 클래스를 사용하여 공유 메모리를 통한 프로세스 간 통신을 구현하는 방법을 보여줍니다. 예제를 빌드하려면 `make`를 실행하십시오. 예제를 실행하려면 실행 파일의 인스턴스를 두 개 시작하십시오. `main()` 함수는 ` application ` 객체와 본 예제의 `Dialog` 클래스 인스턴스를 생성합니다. 대화 상자가 표시된 후, 표준 방식에 따라 제어권이 애플리케이션으로 넘어갑니다.
int main(int argc, char *argv[])
{
QApplication application(argc, argv);
Dialog dialog;
dialog.show();
return application.exec();
}Dialog 클래스의 인스턴스 두 개가 나타납니다.

Dialog 클래스는 QDialog 을 상속받습니다. 이 클래스는 사용자 인터페이스와 QSharedMemory 의 인스턴스를 캡슐화합니다. 또한 대화 상자의 두 버튼에 대응하는 loadFromFile() 및 loadFromMemory()라는 두 개의 공용 슬롯을 가지고 있습니다.
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;
};생성자는 사용자 인터페이스 위젯을 생성하고 각 버튼의 clicked() 신호를 해당 슬롯 함수에 연결합니다.
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"));
}"QSharedMemoryExample"이 키로 사용되도록 QSharedMemory() 생성자에 전달된다는 점에 유의하십시오. 이는 시스템에서 기본이 되는 공유 메모리 세그먼트의 식별자로 사용됩니다.
대화 상자 중 하나에서 Load Image From File... 버튼을 클릭하십시오. loadFromFile() 슬롯이 호출됩니다. 먼저, 공유 메모리 세그먼트가 이미 프로세스에 연결되어 있는지 확인합니다. 연결되어 있다면 해당 세그먼트를 프로세스에서 분리하여 예제를 올바르게 시작할 수 있도록 합니다.
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));그런 다음 사용자에게 ` QFileDialog::getOpenFileName()`를 사용하여 이미지 파일을 선택하도록 요청합니다. 선택된 파일은 ` QImage`에 로드됩니다. ` QImage `를 사용하면 선택된 파일이 유효한 이미지인지 확인할 수 있으며, `setPixmap()`을 사용하여 대화 상자에 이미지를 즉시 표시할 수도 있습니다.
다음으로, QDataStream 를 사용하여 이미지를 QBuffer 로 스트리밍합니다. 이를 통해 이미지 크기를 파악할 수 있으며, 이 크기를 바탕으로 create()를 호출하여 공유 메모리 세그먼트를 할당합니다. 공유 메모리 세그먼트를 생성하면 해당 세그먼트가 프로세스에 자동으로 attaches 됩니다. 여기서 QBuffer 를 사용하면 이미지 데이터에 대한 포인터를 얻을 수 있으며, 이 포인터를 사용하여 QBuffer 에서 공유 메모리 세그먼트로 memcopy()를 수행합니다.
// 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();
}복사 작업을 수행하기 전에 공유 메모리 세그먼트에 대해 lock()을 호출하고, 복사가 끝난 직후 다시 unlock()을 호출한다는 점에 유의하십시오. 이를 통해 memcopy()를 수행하는 동안 공유 메모리 세그먼트에 대한 배타적 접근 권한을 확보할 수 있습니다. 다른 프로세스가 해당 세그먼트의 잠금을 보유하고 있는 경우, 우리 프로세스는 잠금이 해제될 때까지 차단됩니다.
또한 이 함수는 memcopy()와 unlock()을 수행한 후 공유 메모리 세그먼트에서 detach()을 호출하지 않는다는 점에 유의하십시오. 마지막 프로세스가 공유 메모리 세그먼트에서 분리되면 운영 체제가 해당 세그먼트를 해제한다는 사실을 상기하십시오. 현재 이 프로세스만이 공유 메모리 세그먼트에 연결되어 있으므로, 만약 loadFromFile()이 공유 메모리 세그먼트에서 분리된다면, 우리가 다음 단계로 넘어가기 전에 세그먼트가 파괴될 것입니다.
함수가 반환될 때, 선택한 파일이 qt.png라면 첫 번째 대화 상자는 다음과 같이 표시됩니다.

두 번째 대화 상자에서 ‘ Display Image From Shared Memory ’ 버튼을 클릭하세요. loadFromMemory() 슬롯이 호출됩니다. 먼저 첫 번째 프로세스가 생성한 것과 동일한 공유 메모리 세그먼트에 프로세스를 attaches 합니다. 그런 다음 세그먼트에 대한 배타적 액세스 권한을 locks 하고, 공유 메모리 세그먼트 내의 이미지 데이터에 QBuffer 를 연결합니다. 그 후 데이터를 QImage 로 스트리밍하고 세그먼트를 unlocks 합니다.
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));
}이 경우, 해당 함수는 세그먼트에서 ` detach()`를 호출합니다. 이는 이제 해당 세그먼트의 사용이 사실상 완료되었기 때문입니다. 마지막으로, QImage 가 표시됩니다. 이 시점에서 두 대화 상자 모두 동일한 이미지를 표시해야 합니다. 첫 번째 대화 상자를 닫으면, 대화 상자의 소멸자(destructor)가 QSharedMemory 소멸자를 호출하며, 이로 인해 공유 메모리 세그먼트에서 분리됩니다. 이것이 세그먼트에서 분리되는 마지막 프로세스이므로, 운영 체제는 이제 공유 메모리를 해제합니다.
© 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.