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; };
생성자는 사용자 인터페이스 위젯을 빌드하고 각 버튼의 클릭() 신호를 해당 슬롯 함수에 연결합니다.
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 이 표시됩니다. 이 시점에서 두 대화 상자 모두 동일한 이미지가 표시되어야 합니다. 첫 번째 대화 상자를 닫으면 대화 상자 소멸자가 QSharedMemory 소멸자를 호출하여 공유 메모리 세그먼트에서 분리합니다. 이 프로세스가 세그먼트에서 분리되는 마지막 프로세스이므로 이제 운영 체제에서 공유 메모리를 해제합니다.
© 2025 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.