共有メモリ
セマフォ・共有メモリおよび IPC 関数(semaphore)
導入
このモジュールは、System V IPC 関連の関数へのラッパーを提供します。 セマフォ・共有メモリおよびプロセス間通信(IPC)がその中に含まれます。セマフォは、マシーン上のリソースへの排他的アクセス機能や、 同時にあるリソースを使用することができるプロセスの数を制限するために 使用することができます。
このモジュールは、System V 共有メモリを使用した共有メモリ関数も 提供します。共有メモリは、グローバル変数へのアクセス手段を提供するために 使用することが可能です。別の httpd デーモンおよび (Perl, C, ... のような)他のプログラムさえ、グローバルデータ交換を 提供するこのデータにアクセスすることが可能です。 共有メモリは、同時アクセスに関して安全ではないということを覚えておいて ください。 同期をとるには、セマフォを使用してください。 表 263. Unix OS による共有メモリの制限
SHMMAX | 共有メモリの最大サイズ。通常は 131072 バイト |
SHMMIN | 共有メモリの最小サイズ。通常は 1 バイト |
SHMMNI | 共有メモリセグメントの最大数。通常は 100 |
SHMSEG | プロセス毎の共有メモリの最大数。通常は 6 |
メッセージング関数は、他のプロセスと相互にメッセージを送受信する ために使用することができます。 これにより簡単で効率的なプロセス間のデータ交換が可能であり、 Unix ドメインソケットを用いる場合のような設定は不要です。
注意: この拡張モジュールは Windows 環境では利用できません。
要件
外部ライブラリを必要としません。インストール手順
この関数はデフォルトでは有効になってはいません。System V セマフォの サポートを有効にするには、オプション --enable-sysvsem を指定して PHP を コンパイルする必要があります。System V 共有メモリのサポートを有効にするには、 オプション --enable-sysvshm を 指定して PHP をコンパイルする必要があります。System V メッセージを有効に するには、オプション --enable-sysvmsg を指定して PHP をコンパイル します。実行時設定
php.ini の設定により動作が変化します。表 264. セマフォ設定オプション
名前 | デフォルト | 変更の可否 | 変更履歴 |
---|---|---|---|
sysvmsg.value | "42" | PHP_INI_ALL | |
sysvmsg.string | "foobar" | PHP_INI_ALL |
PHP_INI_* 定数の詳細および定義については 付録 G. php.ini ディレクティブ を参照してください。
リソース型
定義済み定数
以下の定数が定義されています。 この関数の拡張モジュールが PHP 組み込みでコンパイルされているか、 実行時に動的にロードされている場合のみ使用可能です。表 265. System V メッセージ定数
定数 | 型 | 変更履歴 |
---|---|---|
MSG_IPC_NOWAIT | integer | |
MSG_EAGAIN | integer | 5.2.0 以降 |
MSG_ENOMSG | integer | 5.2.0 以降 |
MSG_NOERROR | integer | |
MSG_EXCEPT | integer |
目次
- ftok — パス名とプロジェクト ID を、System V IPC キーに変換する
- msg_get_queue — メッセージキューを作成またはそれにアタッチする
- msg_receive — メッセージキューからメッセージを受信する
- msg_remove_queue — メッセージキューを破棄する
- msg_send — メッセージキューにメッセージを送信する
- msg_set_queue — メッセージキューデータ構造体の情報を設定する
- msg_stat_queue — メッセージキューデータ構造体の情報を返す
- sem_acquire — セマフォを得る
- sem_get — セマフォ ID を得る
- sem_release — セマフォを解放する
- sem_remove — セマフォを削除する
- shm_attach — 共有メモリセグメントを作成またはオープンする
- shm_detach — 共有メモリセグメントへの接続を閉じる
- shm_get_var — 共有メモリから変数を返す
- shm_put_var — 共有メモリの変数を挿入または更新する
- shm_remove_var — 共有メモリから変数を削除する
- shm_remove — Unix システムから共有メモリを削除する
共有メモリ
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2025/07/22 23:49 UTC 版)
情報処理において共有メモリ(きょうゆうメモリ)とは、複数のプログラムが同時並行的にアクセスするメモリである。
概要

複数のプログラム間の通信手段として使う場合と、単に複製を用意する冗長さを防ぐ目的の場合などがある。共有メモリはプログラム間でデータをやりとりする効率的手段である。文脈によって、それらプログラムが単一のプロセッサ上で動作する場合と複数の異なるプロセッサ群上で動作する場合がある。単一のプログラムの内部でメモリを使って通信する場合もあり、例えばマルチスレッドが典型的だが、仮想空間をもともと共有している場合は「共有メモリ」とは呼ばない。
ハードウェアによる共有メモリ

コンピュータのハードウェアによる共有メモリは、マルチプロセッサシステムにおける複数のCPUがアクセスできるRAMの(通常)大きなブロックを意味する。
共有メモリシステムでは、全プロセッサがデータを共有しているためプログラミングが比較的容易で、同じメモリ位置へのアクセスによって高速なプロセッサ間通信が可能である。問題は、CPUはなるべく高速なメモリアクセスを必要とするため、それぞれにキャッシュメモリを持っていることが多い点である。そのため、以下の2つの問題が生じる。
- CPU-メモリ間がボトルネックになりやすい。共有メモリ型コンピュータはあまりプロセッサ数を増やせない(CPUを増やしてもCPU数に比例して性能が強化されなくなる)。多くの場合、10個かそれ以下のプロセッサ数である。
- キャッシュコヒーレンシ問題。あるキャッシュ上であるメモリ位置の情報が更新され、それを他のプロセッサが必要とする場合、その更新を他のプロセッサにも反映させなければならない。さもないとそれぞれのプロセッサが一貫していないデータを使って動作することになる。そのためのプロトコルをコヒーレンシプロトコルと呼び、それがうまく機能すれば複数のプロセッサが高速に共有メモリ(上の情報)にアクセスできるようになる。しかし一方で、コヒーレンシプロトコルがオーバーヘッドとなり、性能のボトルネックになることもある。
ボトルネック問題を和らげる技術として、クロスバースイッチ、オメガネットワーク、HyperTransport、CPUバスの分離(フロントサイドバスとバックサイドバス、等)などがある。
共有メモリ以外の方式として分散メモリや分散共有メモリがあるが、どちらにも似たような問題がある。また、NUMAも参照。
GPU内の共有メモリ
GPGPUに対応したモダンなGPUは、GPUのスレッドブロック(ワークグループ、スレッドグループ)内でのみアクセス可能な共有メモリ(ローカルメモリ、グループ共有メモリ)を有している。この共有メモリは、VRAM上に確保されるグローバルメモリと比べると小容量だが高速であり、アプリケーションコードから操作可能なキャッシュメモリの役割を果たす[1]。CUDA、OpenCL、DirectComputeのようなAPIは、それぞれ名称は異なるものの、このGPU共有メモリを利用する機能を持ち、グローバルメモリから読み出したデータをGPUのスレッドブロック内で共有したり、計算結果を交換したりする用途に活用することで、高速化を図ることができる。
ソフトウェアによる共有メモリ
ソフトウェアにおける共有メモリは、以下のいずれかを意味する。
- プロセス間通信 (IPC) の技法の一つ。同時に動作しているプログラム間でデータを交換する方法である。1つのプロセスがメモリ上に他のプロセスからもアクセスできる領域を作成する。
- 通常、アクセスする主体ごとにコピーを用意するようなデータがあるとき、仮想記憶機構や何らかの明示的プログラム機構を使ってそれらが同じ実体(物理メモリ)をアクセスするようマッピングすること。共有ライブラリやXIP (Execute in Place) でよく使われる。
- スレッド実装の一方式
プロセス群は共有メモリ領域に通常のメモリ領域と同じようにアクセスできるので、他のプロセス間通信(名前付きパイプ、ソケット、CORBAなど)と比較して通信手段としては非常に高速である。しかし、プロセス群が同じマシン上で動作しなければならないという制約があり(他のIPC手段はネットワーク上でも機能する)、プロセスが別々のCPU上で動作する場合はハードウェアによる共有メモリを使っていることになり、キャッシュコヒーレンシなどに注意が必要となる。プロセス間の通信がFIFOなストリーム型の場合は、名前付きパイプも通信手段として検討すべきである。一般に共有メモリ自体は保護機能をもたないので動作は高速である。しかし共有されるメモリは不定のタイミングで複数のプロセスからアクセスされる可能性がある。競合を避ける為にはセマフォやロックなどで競合を回避しなければならない。
共有メモリによるIPCは、例えばUNIX上のXサーバとアプリケーションの間で画像を転送する場合や、WindowsのCOMライブラリで CoMarshalInterThreadInterfaceInStream()
関数が返す IStream
オブジェクトの内部で使われている。一般的に共有メモリが使われるアプリケーションとしてOracleなどのデータベースがある。Unix版OracleではSGAと呼ばれる共有メモリ空間にデータベースバッファキャッシュがおかれて複数のプロセスからアクセスさせて性能の向上を図っている。
動的ライブラリは一度メモリ上に置かれると、それが複数のプロセスにマッピングされ、プロセスごとにカスタマイズされるページ群(シンボル解決に違いが生じる部分)だけが複製され、通常コピーオンライトという機構で、そのページに書き込もうとしたときにコピーが行われる。
UNIXでのサポート
POSIX には共有メモリの標準化APIとして POSIX Shared Memory がある。これは、sys/mman.h にある shm_open
という関数を使う[2]。POSIXのプロセス間通信(POSIX:XSI拡張の一部)には共有メモリ関数として shmat
、shmctl
、shmdt
が含まれている[3][4]。
shm_open
で生成された共有メモリは永続的であり、プロセスが明示的に削除しない限りシステム内に存在し続ける。ただしこれには欠点もあり、共有メモリを削除すべきプロセスがその前に異常終了したとき、その共有メモリがシステムのシャットダウンまで残存し続けることになる。そのような問題を避けるには、mmapを使って共有メモリを作成すればよい[5]。2つの通信しあうプロセスが同じ名前の一時ファイルをオープンし、それに対してmmapすることでファイルをメモリにマッピングする。結果として、メモリマップされたファイル(メモリマップトファイル)への変更はもう一方のプロセスからも同時に観測できる。この技法の利点は、両方のプロセスが終了したとき、OSが自動的にファイルをクローズし、共有メモリを削除する点である。
Linuxカーネル 2.6 では、RAMディスク形式の共有メモリとして /dev/shm が導入された。より正確に言えば、誰でも書き込めるメモリ内のディレクトリであり、その容量の上限は /etc/default/tmpfs で指定できる。/dev/shm 機能サポートはカーネルの設定ファイルで指定でき、デフォルトでは無効となっている。なお、RedHat や Debian ベースのディストリビューションではデフォルトで有効になっている。
Androidでのサポート
Android では Linux カーネルを使用しているが、IPC 関係が一部無効になっており、独自に開発した(現在はLinuxカーネルに入っている)ashmem (anonymous shared memory) を使用している。メモリが不足したときにカーネルが解放する仕組みがあり、解放されないようにするには、ashmem_pin_region()
を使い指定する。
Windowsでのサポート
Microsoft Windowsでは、Win32 APIのCreateFileMapping()
関数を使って共有メモリ(メモリマップトファイル)を作成することができる[6]。クライアント側プロセスはOpenFileMapping()
関数を使って、ホスト側プロセスにて作成済みの共有メモリのハンドルを取得することができる。共有メモリを各プロセスのアドレス空間にマッピングするにはMapViewOfFile()
関数を使う。
なおWindows APIには、CreateSharedMemory()
[7][8]など “-SharedMemory” の名前を持つ関数があるが、これはセキュリティ関連のAPIであり、メモリ共有のためのAPIではない。これをメモリ共有のために使用すれば、リソースを大量に消費しシステムリソースを使い果たす可能性がある。
プログラミング言語ごとのサポート
一部のC++ライブラリは、共有メモリ機能への移植性の高いオブジェクト指向的なアクセスを提供している。例えば、Boost C++ライブラリには Boost.Interprocess があり[9]、POCO C++ Libraries には Poco::SharedMemory、Qt には QSharedMemory クラスがある[10]。
PHP では POSIX で定義している関数群とよく似た共有メモリ用APIが存在する[11]。
.NET Frameworkはバージョン4でSystem.IO.MemoryMappedFiles.MemoryMappedFile
クラス[12]を標準化した。.NETあるいはXamarin (Mono) を通じて、Windows以外の他のプラットフォームでも利用できる。
脚注
- ^ CUDAプログラミングの基本 / パート II - カーネル | NVIDIA
- ^ Documentation of shm_open from the Single UNIX Specification
- ^ Robbins, Kay A.; Steven Robbins (2003). UNIX systems programming: communication, concurrency, and threads (2 ed.). Prentice Hall PTR. p. 512. ISBN 978-0-13-042411-2 2011年5月13日閲覧. "The POSIX interprocess communication (IPC) is part of the POSIX:XSI Extension and has its origin in UNIX System V interprocess communication."
- ^ Shared memory facility from the Single UNIX Specification.
- ^ Stevens, Richard (1999). UNIX Network Programming, Volume 2, Second Edition: Interprocess Communications. (2 ed.). Prentice Hall PTR. p. 311. ISBN 0-13-081081-9
- ^ Creating Named Shared Memory - Windows applications | Microsoft Docs
- ^ CreateSharedMemory function (Windows), Internet Archive
- ^ LSA_CREATE_SHARED_MEMORY (ntsecpkg.h) - Win32 apps | Microsoft Learn
- ^ Chapter 16. Boost.Interprocess - 1.80.0
- ^ QSharedMemory Class Reference
- ^ PHP 共有メモリ関数
- ^ MemoryMappedFile Class (System.IO.MemoryMappedFiles) | Microsoft Docs
関連項目
学習参考書
- Julian Shun: "Shared-Memory Parallelism Can be Simple, Fast, and Scalable", ACM books, ISBN 978-1-97000-191-4, doi:10.1145/3018787 (2017).
外部リンク
shm_overview(7)
– JM Project Linux Overview, Conventions and Miscellanea マニュアル- IPC:Shared Memory by Dave Marshall
- Shared Memory Introduction, Ch. 12 from book by Richard Stevens "UNIX Network Programming, Volume 2, Second Edition: Interprocess Communications".
共有メモリ
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2022/03/18 09:34 UTC 版)
GPUによるVRAMへのアクセスは、複数のプロセッサ群によって並列的に発生するため、連続したメモリ領域に対するコアレスアクセス(coalesce access、≒シーケンシャルアクセス)を行なうことで効率化・高速化できる。NVIDIA GPUでは32のハードウェアスレッドを束ねるバッチ単位をWarpと呼び、AMD GPUでは64のハードウェアスレッドを束ねるバッチ単位をWavefrontと呼んでいるが、これらのユニット内ではプロセッサが完全に同期して動作するため、バッチ単位ごとにまとめて連続領域にアクセス(コアレスアクセス)することで効率が良くなる。逆に言えば、バッチ単位内のスレッドがそれぞれ遠く離れたばらばらのアドレスにアクセスするような非コアレスアクセス(≒ランダムアクセス)は効率が悪くなる。 GPGPUの本質は、大量の演算器によって実現されるハードウェアマルチスレッド集合を用いたデータ並列演算により性能を稼ぐ点にある。例えばNVIDIA GPUのFermi/Keplerマイクロアーキテクチャでは、演算器の最小単位をCUDAコア (SP, streaming processor) と呼び、また複数のCUDAコアを束ねる単位をSMX (SM, streaming multiprocessor) と呼んでいるが、GPUでの演算は、複数のSMXに対して同一の命令を発行していき、各々のハードウェアスレッドに割り当てられたデータに対して並列的に演算を行なうスタイルとなる。またWarp単位内における各スレッドはすべて同一の命令を実行する(SIMT(英語版))。基本概念としてはAMDのVLIWやGraphics Core NextといったGPUアーキテクチャにおいても同様である。 しかし、このGPGPUプログラミングが特に従来型のCPUプログラミングと異なる点は、共有メモリ(shared memory、シェアードメモリ)の存在である。共有メモリは小容量だが高速で、ユーザープログラマーが明示的に管理できるキャッシュメモリ(≒L1キャッシュ)の仕組みを果たし、複数のコアでデータを共有・交換する目的に使用できる。なお各APIにおいては、CUDAは共有メモリ、OpenCLはローカルメモリ、DirectComputeはグループ共有メモリ、そしてC++ AMPはタイル静的メモリという名称で、それぞれ同等機能を備えている。 例えばFermi/Keplerマイクロアーキテクチャでは、1SMXあたり最大48KBの共有メモリを使用できるが、外部にあるDRAMにキャッシュなしでアクセスする場合と比べて、共有メモリのレイテンシは(スレッド間のバンクコンフリクトがないかぎり)100倍小さくなる。そのため、複数のスレッドから参照されるデータの一時書き込み場所として共有メモリを活用することにより、高速な並列アルゴリズム(たとえば高速に総和を求める並列リダクションなど)や、GPUプログラミングにおける高速化に必要なコアレスアクセス(≒シーケンシャルアクセス)を実現することができるとNVIDIAは説明している。しかしながら、最大でも48KBしかない共有メモリというハードウェア制約がアルゴリズムの幅に制限をかけるため、共有メモリの存在はGPUプログラミングの難しさにもつながってしまう。また、共有メモリに読み書きする際、スレッド間の同期をとるための処理もプログラマーが明示的に記述する必要がある。 なお、インテルCPUのL2キャッシュメモリはL1キャッシュメモリに比べて容量が大きく、またプロセッサコア側に直結されているが、NVIDIA GPUのL2キャッシュメモリはL1キャッシュメモリに比べて容量がほとんど変わらず、またメモリ側に直結されているなど、データアクセス傾向の違いがハードウェア設計思想の違いにも反映されており、単純にキャッシュメモリの容量だけを比較して性能の優劣を決めることはできない 。
※この「共有メモリ」の解説は、「GPGPU」の解説の一部です。
「共有メモリ」を含む「GPGPU」の記事については、「GPGPU」の概要を参照ください。
固有名詞の分類
- 共有メモリのページへのリンク