このページでは

共有メモリ

Qt XML では、同じシステム内の他のプロセスとメモリを共有するために、QSharedMemory およびQFile を使用したメモリマップドファイルという 2 つの手法を提供しています。他のプロセスと共有されるメモリは、しばしば「セグメント」と呼ばれますが、以前はセグメント化されたメモリモデルを持つプロセッサ上で特定のセグメントとして実装されていたこともありますが、現代のオペレーティングシステムではそうではありません。 共有メモリセグメントとは、単に、オペレーティングシステムが参加するすべてのプロセスが利用できるように保証するメモリ領域のことです。

注: メモリ内でのセグメントの位置アドレスは 、共有に参加しているプロセスごとにほぼ常に異なります。したがって、アプリケーションは、C++のプリミティブ型やそのような型の配列など、位置に依存しないデータのみを共有するように注意する必要があります。

QSharedMemory を使用したメモリの共有

QSharedMemory は、指定されたサイズの共有メモリセグメントを作成したり、別のプロセスによって作成されたセグメントにアタッチしたりするためのシンプルな API を提供します。さらに、内部のQSystemSemaphore を使用して、セグメント全体をlock およびunlock するための 2 つのメソッドも提供します。

共有メモリセグメントとシステムセマフォは、システム内で「キー」によって一意に識別されます。Qt では、このキーはQNativeIpcKey クラスによって表されます。また、OS によっては、Qt がメモリ共有のために複数の異なるバックエンドをサポートしている場合があります。詳細および制限事項については、「Native IPC Keys」のドキュメントを参照してください。

QSharedMemory は、同じ特権レベル内でのみメモリを共有するように設計されています(つまり、他のユーザーによって起動されたプロセスなど、信頼できない他のプロセスとは共有しません)。これをサポートするバックエンドの場合、QSharedMemory は、同じ特権レベルを持つプロセスのみがアタッチできるようにセグメントを作成します。

メモリマップドファイルを介したメモリ共有

ほとんどのファイルは `QFile::map()` を使用してメモリにマップできます。また、MapPrivateOption オプションが指定されていない場合、マップされたセグメントへの書き込みは、同じファイルをマップしている他のすべてのプロセスから確認されます。メモリにマップできないファイルの例外には、ネットワーク共有にあるリモートファイルや、特定のファイルシステムにあるファイルなどが含まれます。 たとえオペレーティングシステムがリモートファイルのメモリへのマッピングを許可していたとしても、そのファイルに対するI/O操作はキャッシュされ、遅延する可能性が高い。そのため、真の意味でのメモリ共有は不可能となる。

このソリューションには、バックエンド API に依存しないこと、および Qt 以外のアプリケーションとの相互運用が容易であるという大きな利点があります。QTemporaryFile はQFile であるため、アプリケーションはこのクラスを使用してクリーンアップセマンティクスを実現し、一意の共有メモリセグメントを作成することもできます。

共有メモリセグメントのロックを実現するには、アプリケーションが独自のメカニズムを実装する必要があります。その方法の一つとして、QLockFile を使用することが考えられます。もう一つの、より負荷の少ない解決策は、セグメント内のあらかじめ決められたオフセット位置でQAtomicInteger または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 を参照)を使用する方法があります。systemd を使用する Linux システムでは、これはユーザー固有のtmpfs となります。

さらに安全な解決策としては、memfd_create(2) を使用して「memfd」を作成し、QDBusUnixFileDescriptor のようにプロセス間通信でファイルディスクリプタを渡すか、QProcess の子プロセスにそれを継承させる方法があります。「memfd」はサイズが縮小されないよう保護することもできるため、異なる権限レベルを持つプロセスとの通信でも安全に使用できます。

FreeBSDにおけるメモリマップドファイルに関するヒント

FreeBSD にも `memfd_create(2) ` があり、Linux と同じ手法を使って他のプロセスにファイルディスクリプタを渡すことができます。デフォルトでは、一時ファイルシステムはマウントされていません。

Windowsにおけるメモリマップドファイルに関するヒント

Windowsでは、アプリケーションがオペレーティングシステムに対し、ファイルの内容を永続的なストレージに保存しないよう要求することができます。この要求は、Win32関数CreateFile のdwFlagsAndAttributes パラメータにFILE_ATTRIBUTE_TEMPORARY フラグを指定するか、低レベル関数_open() に_O_SHORT_LIVED フラグを指定するか、あるいはCランタイム関数fopen() に修飾子「T」を含めることで行われます。

また、ファイルへの最後のハンドルが閉じられた際に、オペレーティングシステムにファイルを削除するよう指示するフラグ(FILE_FLAG_DELETE_ON_CLOSE 、_O_TEMPORARY 、および修飾子「D」)もありますが、ファイルを開こうとするすべてのプロセスが、このフラグを使用するか否かについて合意している必要がある点に注意してください。合意が一致しない場合、共有違反が発生し、ファイルのオープンに失敗する可能性があります。

© 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.