メモリの共有
Qt は、同じシステム内の他のプロセスとメモリを共有するために、QSharedMemory と、QFile を使ったメモリマップファイルという 2 つの手法を提供しています。他のプロセスと共有されるメモリは、しばしば「セグメント」と呼ばれます。以前は、セグメント化されたメモリモデルを持つプロセッサ上で、特定のセグメントとして実装されていたかもしれませんが、現代のオペレーティングシステムではそうではありません。共有メモリー・セグメントは、オペレーティング・システムが、参加するすべてのプロセスが利用できるようにする、単なるメモリーの領域です。
注意: セグメントをメモリ上に配置するアドレスは、共有に参加するプロセスごとに異なることがほとんどです。したがって、アプリケーションは、プリミティブ C++ 型やそのような型の配列など、位置に依存しないデータのみを共有するように注意する必要があります。
QSharedMemory を使用したメモリの共有
QSharedMemory は、指定されたサイズの共有メモリ・セグメントを作成したり、他のプロセスによって作成されたセグメントにアタッチしたりするためのシンプルな API を提供します。さらに、内部メソッド を使用して、セグメント全体を および するためのメソッドも提供します。QSystemSemaphore lock unlock
QNativeIpcKey 共有メモリセグメントとシステムセマフォは、システム内で「キー」によってグローバルに識別されます。さらに、OSによっては、Qtはメモリを共有するための複数の異なるバックエンドをサポートすることがあります。詳細と制限については、Native IPC Keysのドキュメントを参照してください。
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 Runtime Directory(QStandardPaths::writableLocation ()およびQStandardPaths::RuntimeLocation ()を参照)を使用することもできます。systemdを使用しているLinuxシステムでは、ユーザー固有のtmpfs
。
さらに安全な解決策は、memfd_create(2)
を使用して "memfd" を作成し、QDBusUnixFileDescriptor のように、またはQProcess の子プロセスに継承させることで、プロセス間通信を使用してファイル記述子を渡すことである。"memfd" はシュリンクされないように封印することもできるので、 異なる特権レベルのプロセスと通信する際にも安全に使うことができます。
メモリマップされたファイルに関する FreeBSD のヒント
FreeBSD にもmemfd_create(2)
があり、Linux と同じ手法でファイルディスクリプタを他のプロセスに渡すことができます。デフォルトでは一時ファイルシステムはマウントされていません。
Windows メモリマップドファイルのヒント
Windowsでは、アプリケーションはオペレーティング・システムに対して、ファイルの内容を永久記憶装置に保存しないように要求することができる。この要求は、CreateFile
Win32関数のdwFlagsAndAttributes
パラメータにFILE_ATTRIBUTE_TEMPORARY
フラグを渡すか、_open()
低レベル関数に_O_SHORT_LIVED
フラグを渡すか、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.