共有メモリ

情報処理において共有メモリ（きょうゆうメモリ）とは、複数のプログラムが同時並行的にアクセスするメモリである。
概要.
複数のプログラム間の通信手段として使う場合と、単に複製を用意する冗長さを防ぐ目的の場合などがある。共有メモリはプログラム間でデータをやりとりする効率的手段である。文脈によって、それらプログラムが単一のプロセッサ上で動作する場合と複数の異なるプロセッサ群上で動作する場合がある。単一のプログラムの内部でメモリを使って通信する場合もあり、例えばマルチスレッドが典型的だが、仮想空間をもともと共有している場合は「共有メモリ」とは呼ばない。
ハードウェアによる共有メモリ.
コンピュータのハードウェアによる共有メモリは、マルチプロセッサシステムにおける複数のCPUがアクセスできるRAMの（通常）大きなブロックを意味する。
共有メモリシステムでは、全プロセッサがデータを共有しているためプログラミングが比較的容易で、同じメモリ位置へのアクセスによって高速なプロセッサ間通信が可能である。問題は、CPUはなるべく高速なメモリアクセスを必要とするため、それぞれにキャッシュメモリを持っていることが多い点である。そのため、以下の2つの問題が生じる。
ボトルネック問題を和らげる技術として、クロスバースイッチ、、HyperTransport、CPUバスの分離（フロントサイドバスとバックサイドバス、等）などがある。
共有メモリ以外の方式としてや分散共有メモリがあるが、どちらにも似たような問題がある。また、NUMAも参照。
ソフトウェアによる共有メモリ.
ソフトウェアにおける共有メモリは、以下のいずれかを意味する。
プロセス群は共有メモリ領域に通常のメモリ領域と同じようにアクセスできるので、他のプロセス間通信（名前付きパイプ、ソケット、CORBAなど）と比較して通信手段としては非常に高速である。しかし、プロセス群が同じマシン上で動作しなければならないという制約があり（他のIPC手段はネットワーク上でも機能する）、プロセスが別々のCPU上で動作する場合はハードウェアによる共有メモリを使っていることになり、キャッシュコヒーレンシなどに注意が必要となる。プロセス間の通信がFIFOなストリーム型の場合は、名前付きパイプも通信手段として検討すべきである。一般に共有メモリ自体は保護機能をもたないので動作は高速である。しかし共有されるメモリは不定のタイミングで複数のプロセスからアクセスされる可能性がある。競合を避ける為にはセマフォやロックなどで競合を回避しなければならない。
共有メモリによるIPCは、例えばUNIX上のXサーバとアプリケーションの間で画像を転送する場合や、WindowsのCOMライブラリで codice_1 関数が返す codice_2 オブジェクトの内部で使われている。一般的に共有メモリが使われるアプリケーションとしてOracleなどのデータベースがある。Unix版OracleではSGAと呼ばれる共有メモリ空間にデータベースバッファキャッシュがおかれて複数のプロセスからアクセスさせて性能の向上を図っている。
動的ライブラリは一度メモリ上に置かれると、それが複数のプロセスにマッピングされ、プロセスごとにカスタマイズされるページ群（シンボル解決に違いが生じる部分）だけが複製され、通常コピーオンライトという機構で、そのページに書き込もうとしたときにコピーが行われる。
UNIXでのサポート.
POSIX には共有メモリの標準化APIとして "POSIX Shared Memory" がある。これは、sys/mman.h にある codice_3 という関数を使う。POSIXのプロセス間通信（POSIX:XSI拡張の一部）には共有メモリ関数として codice_4、codice_5、codice_6 が含まれている。
codice_3 で生成された共有メモリは永続的であり、プロセスが明示的に削除しない限りシステム内に存在し続ける。ただしこれには欠点もあり、共有メモリを削除すべきプロセスがその前に異常終了したとき、その共有メモリがシステムのシャットダウンまで残存し続けることになる。そのような問題を避けるには、mmapを使って共有メモリを作成すればよい。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) を使用している。メモリが不足したときにカーネルが解放する仕組みがあり、解放されないようにするには、codice_8 を使い指定する。
Windowsでのサポート.
Microsoft Windowsでは、Win32 APIのcodice_9関数を使って共有メモリ（メモリマップトファイル）を作成することができる。クライアント側プロセスはcodice_10関数を使って、ホスト側プロセスにて作成済みの共有メモリのハンドルを取得することができる。共有メモリを各プロセスのアドレス空間にマッピングするにはcodice_11関数を使う。
なおWindows APIには、codice_12 など “-SharedMemory” の名前を持つ関数があるが、これはセキュリティ関連のAPIであり、メモリ共有のためのAPIではない。これをメモリ共有のために使用すれば、リソースを大量に消費しシステムリソースを使い果たす可能性がある。
プログラミング言語ごとのサポート.
一部のC++ライブラリは、共有メモリ機能への移植性の高いオブジェクト指向的なアクセスを提供している。例えば、Boost C++ライブラリには Boost.Interprocess があり、POCO C++ Libraries には Poco::SharedMemory、Qt には QSharedMemory クラスがある。
PHP では POSIX で定義している関数群とよく似た共有メモリ用APIが存在する。
.NET Frameworkはバージョン4でcodice_13クラスを標準化した。.NET CoreあるいはXamarin (Mono) を通じて、Windows以外の他のプラットフォームでも利用できる。