공유 메모리
Qt는 같은 시스템의 다른 프로세스와 메모리를 공유하는 두 가지 기법을 제공합니다: QSharedMemory 과 QFile 을 이용한 메모리 매핑 파일. 다른 프로세스와 공유되는 메모리는 종종 "세그먼트"라고 불리며, 과거에는 세그먼트 메모리 모델을 가진 프로세서에서 특정 세그먼트로 구현되었을 수 있지만, 최신 운영 체제에서는 그렇지 않습니다. 공유 메모리 세그먼트는 운영 체제에서 참여하는 모든 프로세스가 사용할 수 있도록 보장하는 메모리 영역일 뿐입니다.
참고: 세그먼트가 메모리에서 위치하는 주소는 공유에 참여하는 각 프로세스마다 거의 항상 다릅니다. 따라서 애플리케이션은 원시 C++ 타입이나 이러한 타입의 배열과 같이 위치에 독립적인 데이터만 공유하도록 주의해야 합니다.
QSharedMemory를 사용한 메모리 공유
QSharedMemory 는 주어진 크기의 공유 메모리 세그먼트를 생성하거나 다른 프로세스에서 생성한 세그먼트에 연결할 수 있는 간단한 API를 제공합니다. 또한 내부 QSystemSemaphore 을 사용하여 lock 및 unlock 전체 세그먼트에 대한 한 쌍의 메서드를 제공합니다.
공유 메모리 세그먼트와 시스템 세마포어는 "키"를 통해 시스템에서 전역적으로 식별되며, Qt에서는 QNativeIpcKey 클래스로 표현됩니다. 또한 OS에 따라 Qt는 메모리 공유를 위한 여러 가지 백엔드를 지원할 수 있습니다; 자세한 정보와 제한 사항은 네이티브 IPC 키 문서를 참조하십시오.
QSharedMemory 는 동일한 권한 수준 내에서만 메모리를 공유하도록 설계되었습니다(즉, 다른 사용자가 시작한 프로세스 등 신뢰할 수 없는 다른 프로세스와는 공유하지 않음). 이를 지원하는 백엔드의 경우 QSharedMemory 에서 동일한 권한 수준의 프로세스만 연결할 수 있도록 세그먼트를 생성합니다.
메모리 매핑된 파일을 통한 메모리 공유
대부분의 파일은 QFile::map()를 사용하여 메모리에 매핑할 수 있으며, MapPrivateOption 옵션을 지정하지 않으면 매핑된 세그먼트에 대한 모든 쓰기는 동일한 파일을 매핑한 다른 모든 프로세스에서 관찰됩니다. 메모리에 매핑할 수 있는 파일에는 네트워크 공유에 있는 원격 파일이나 특정 파일시스템에 있는 파일은 예외입니다. 운영 체제에서 원격 파일을 메모리에 매핑하는 것을 허용하더라도 파일에 대한 I/O 작업이 캐시되어 지연될 수 있으므로 진정한 메모리 공유가 불가능합니다.
이 솔루션은 백엔드 API와 독립적이며 Qt가 아닌 애플리케이션에서 상호 운용하기가 더 간단하다는 주요 이점이 있습니다. QTemporaryFile 은 QFile 이므로 애플리케이션은 해당 클래스를 사용하여 정리 시맨틱을 달성하고 고유한 공유 메모리 세그먼트도 생성할 수 있습니다.
공유 메모리 세그먼트의 잠금을 달성하려면 애플리케이션이 자체 메커니즘을 배포해야 합니다. 한 가지 방법은 QLockFile 을 사용하는 것입니다. 비용이 적게 드는 또 다른 방법은 세그먼트 자체에 미리 결정된 오프셋에 QBasicAtomicInteger 또는 std::atomic
를 사용하는 것입니다. 일부 운영 체제에서는 더 높은 수준의 잠금 프리미티브를 사용할 수 있습니다. 예를 들어 Linux에서는 애플리케이션이 pthread_mutex_create()
에 전달되는 뮤텍스 속성에 "pshared" 플래그를 설정하여 뮤텍스가 공유 메모리 세그먼트에 있음을 나타낼 수 있습니다.
운영 체제에서 공유 메모리에 대한 모든 쓰기를 영구 저장소에 커밋하려고 시도할 가능성이 높다는 점에 유의하세요. 이는 바람직한 현상일 수도 있고 파일 자체가 일시적인 것이라면 성능 저하로 이어질 수도 있습니다. 이 경우 애플리케이션은 Linux의 tmpfs
( QStorageInfo::fileSystemType() 참조)와 같은 RAM 지원 파일 시스템을 찾거나 기본 파일 열기 함수에 플래그를 전달하여 콘텐츠가 스토리지에 커밋되지 않도록 OS에 알려야 합니다.
파일 백업 공유 메모리를 사용하여 신뢰할 수 없는 프로세스와 통신할 수 있는데, 이 경우 애플리케이션은 각별히 주의해야 합니다. 파일이 잘리거나 축소되어 파일 크기를 초과하여 메모리에 액세스하는 애플리케이션이 충돌을 일으킬 수 있습니다.
메모리 매핑 파일에 대한 Linux 힌트
최신 Linux 시스템에서는 /tmp
디렉터리가 tmpfs
마운트 지점이 되는 경우가 많지만, 반드시 그렇게 해야 하는 것은 아닙니다. 그러나 /dev/shm
디렉터리는 tmpfs
디렉터리여야 하며 메모리 공유를 목적으로 존재합니다. 이 디렉터리는 /tmp
및 /var/tmp
과 같이 전 세계에서 읽고 쓸 수 있으므로 애플리케이션은 여기에 공개되는 콘텐츠에 주의해야 합니다. 또 다른 대안은 XDG 런타임 디렉터리( QStandardPaths::writableLocation() 및 QStandardPaths::RuntimeLocation 참조)를 사용하는 것인데, 시스템드를 사용하는 Linux 시스템에서는 사용자 전용 tmpfs
을 사용합니다.
더 안전한 솔루션은 memfd_create(2)
을 사용하여 "memfd"를 만들고 프로세스 간 통신을 사용하여 QDBusUnixFileDescriptor 과 같이 파일 설명자를 전달하거나 QProcess 의 하위 프로세스가 이를 상속하도록 하는 것입니다. "memfd"는 축소되지 않도록 봉인할 수도 있으므로 다른 권한 수준을 가진 프로세스와 통신할 때 안전하게 사용할 수 있습니다.
메모리 매핑 파일에 대한 FreeBSD 힌트
FreeBSD에도 memfd_create(2)
가 있으며 Linux와 동일한 기술을 사용하여 파일 기술자를 다른 프로세스에 전달할 수 있습니다. 기본적으로 임시 파일 시스템이 마운트되어 있지 않습니다.
메모리 매핑 파일에 대한 Windows 힌트
Windows에서는 애플리케이션이 운영 체제에 파일 내용을 영구 저장소에 저장하지 않도록 요청할 수 있습니다. 이 요청은 dwFlagsAndAttributes
매개변수에 FILE_ATTRIBUTE_TEMPORARY
플래그를 CreateFile
Win32 함수에, _O_SHORT_LIVED
플래그를 _open()
로우레벨 함수에 전달하거나 fopen()
C 런타임 함수에 수정자 "T"를 포함하여 수행됩니다.
또한 파일에 대한 마지막 핸들이 닫힐 때 운영 체제에 파일을 삭제하도록 알리는 플래그(FILE_FLAG_DELETE_ON_CLOSE
, _O_TEMPORARY
, "D" 수정자)도 있지만 파일을 열려고 하는 모든 프로세스가 이 플래그 사용 또는 미사용에 동의해야 한다는 점에 유의하세요. 일치하지 않으면 공유 위반이 발생하여 파일을 열지 못할 가능성이 높습니다.
© 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.