共有メモリ
情報処理において共有メモリ(きょうゆう-)とは、複数のプログラムが同時並行的にアクセスするメモリであり、それらプログラム間の通信手段として使う場合と、単に複製を用意する冗長さを防ぐ目的の場合などがある。文脈によって、それらプログラムが単一のプロセッサ上で動作する場合と複数の異なるプロセッサ群上で動作する場合がある。単一のプログラムの内部でメモリを使って通信する場合もあり、例えばマルチスレッドが典型的だが、仮想空間をもともと共有している場合は「共有メモリ」とは呼ばない。
目次 |
[編集] ハードウェアによる共有メモリ
コンピュータのハードウェアによる共有メモリは、マルチプロセッサシステムにおける複数のCPUがアクセスできるRAMの(通常)大きなブロックを意味する。
共有メモリシステムでは、全プロセッサがデータを共有しているためプログラミングが比較的容易で、同じメモリ位置へのアクセスによって高速なプロセッサ間通信が可能である。
問題は、CPUはなるべく高速なメモリアクセスを必要とするため、それぞれにキャッシュメモリを持っていることが多い点である。そのため、以下の2つの問題が生じる。
- CPU-メモリ間がボトルネックになりやすい。共有メモリ型コンピュータはあまりプロセッサ数を増やせない(CPUを増やしても性能がCPU数に比例して強化されなくなる)。多くの場合、10個かそれ以下のプロセッサ数である。
- キャッシュコヒーレンシ問題。あるキャッシュ上であるメモリ位置の情報が更新され、それを他のプロセッサが必要とする場合、その更新を他のプロセッサにも反映させなければならない。さもないとそれぞれのプロセッサが一貫していないデータを使って動作することになる。そのためのプロトコルをコヒーレンシプロトコルと呼び、それがうまく機能すれば複数のプロセッサが高速に共有メモリ(上の情報)にアクセスできるようになる。しかし一方で、コヒーレンシプロトコルがオーバーヘッドとなり、性能のボトルネックになることもある。
共有メモリ以外の方式として分散メモリや分散共有メモリがあるが、どちらにも似たような問題がある。また、NUMAも参照。
[編集] ソフトウェアによる共有メモリ
ソフトウェアにおける共有メモリは、以下のいずれかを意味する。
- プロセス間通信 (IPC) の技法の一つ。同時に動作しているプログラム間でデータを交換する方法である。1つのプロセスがメモリ上に他のプロセスからもアクセスできる領域を作成する。
- 通常、アクセスする主体ごとにコピーを用意するようなデータがあるとき、仮想記憶機構や何らかの明示的プログラム機構を使ってそれらが同じ実体(物理メモリ)をアクセスするようマッピングすること。共有ライブラリやXIP (Execute in Place) でよく使われる。
- スレッド実装の一方式
プロセス群は共有メモリ領域に通常のメモリ領域と同じようにアクセスできるので、他のプロセス間通信(名前付きパイプ、ソケット、CORBAなど)と比較して通信手段としては非常に高速である。しかし、プロセス群が同じマシン上で動作しなければならないという制約があり(他のIPC手段はネットワーク上でも機能する)、プロセスが別々のCPU上で動作する場合はハードウェアによる共有メモリを使っていることになり、キャッシュコヒーレンシなどに注意が必要となる。プロセス間の通信がFIFOなストリーム型の場合は、名前付きパイプも通信手段として検討すべきである。一般に共有メモリ自体は保護機能をもたないので動作は高速である。しかし共有されるメモリは不定のタイミングで複数のプロセスからアクセスされる可能性がある。競合を避ける為にはセマフォやロックなどで競合を回避しなければならない。
共有メモリによるIPCは、例えばUNIX上のXサーバとアプリケーションの間で画像を転送する場合や、WindowsのCOMライブラリで CoMarshalInterThreadInterfaceInStream が返す IStream オブジェクトの内部で使われている。一般的に共有メモリが使われるアプリケーションとしてOracleなどのデータベースがある。Unix版OracleではSGAと呼ばれる共有メモリ空間にデータベースバッファキャッシュがおかれて複数のプロセスからアクセスさせて性能の向上を図っている。
動的ライブラリは一度メモリ上に置かれると、それが複数のプロセスにマッピングされ、プロセスごとにカスタマイズされるページ群(シンボル解決に違いが生じる部分)だけが複製され、通常コピーオンライトという機構で、そのページに書き込もうとしたときにコピーが行われる。
POSIX には共有メモリの標準化APIとして POSIX Shared Memory がある。これは、sys/mman.h にある shm_open という関数を使う。
UNIX System V にも共有メモリのためのAPIが存在する。こちらは sys/shm.h にある shmget を使う。
BSD系システムでは、匿名マップトメモリを複数のプロセスで使うことができる。
Linuxカーネル 2.6 では、RAMディスク形式の共有メモリとして /dev/shm が導入された。より正確に言えば、誰でも書き込めるメモリ内のディレクトリであり、その容量の上限は /etc/default/tmpfs で指定できる。/dev/shm 機能サポートはカーネルの設定ファイルで指定でき、デフォルトでは無効となっている。なお、Fedora や Ubuntu ではデフォルトで有効になっている。PulseAudio のアプリケーションは、この機能を多用している。
Microsoft WindowsのWin32 APIではCreateFileMapping関数でファイルハンドルとしてINVALID_HANDLE_VALUEを指定することで共有メモリを作れる。また、このやり方で、カーネルモードとユーザーモードの間で共有メモリを作ることも出来る。[1]
[編集] 関連項目
[編集] 外部リンク
- Shared Memory Allocation
- Shared Memory Interface
- Shared Memory Library FAQ by Márcio Serolli Pinho
- Article "IPC:Shared Memory" by Dave Marshall
- shared memory facility from the Single UNIX Specification
- shm_open - POSIX
- shmop - documentation from SunOS 5.9
- CreateSharedMemory function from Win32-SDK
- Functions in PHP-API
- "A C++ Pooled, Shared Memory Allocator For The Standard Template Library" by Marc Ronell
- Linux Shared Memory Allocation with example
- Boost.Interprocess C++ Library