#include <sys/types.h> #include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
shmaddr が NULL ならば、システムはセグメントを付加するための 適切な (使用されていない) アドレスを選択する。
shmaddr が NULL でなく SHM_RND が shmflg に指定されている場合は、 shmaddr を SHMLBA の倍数へと切り捨てた (rounding down) のと等しいアドレスへ付加する。 その他の場合は shmaddr は付加を行なうアドレスで、ページ境界を指している必要がある。
SHM_RDONLY が shmflg に指定されていた場合は、 セグメントは読み込み専用に付加され、プロセスはそのセグメントへの 読み込み許可を持たなければならない。 そうでなければそのセグメントは読み込みと書き込みのために付加され、 プロセスはそのセグメントに読み込みと書き込みの許可を持つ必要がある。 書き込み専用の共有メモリ・セグメントという概念は存在しない。
(Linux 特有の) SHM_REMAP フラグが shmflg に指定された場合は、 セグメントのマッピングを既存のマッピングに置き換える。 マッピングの範囲は、 shmaddr から始まりセグメントのサイズ分だけある (通常 EINVAL エラーは、このアドレス範囲にマッピングが既に存在するために起る)。 このフラグを指定する場合は、 shmaddr が NULL であってはならない。
呼び出したプロセスの brk(2) の値は付加によって変化しない。 そのセグメントはプロセスが終了 (exit) したら自動的に分離 (detach) される。 同じセグメントをプロセスのアドレス空間に、読み込み専用および読み書き両用 として付加でき、また複数回付加することもできる。
成功した shmat() コールは共有メモリ・セグメントに関連する shmid_ds 構造体 (shmctl(2) を参照) のメンバーを以下のように更新する:
shmdt() は呼び出したプロセスのアドレス空間から shmaddr で指定されたアドレスに配置された共有メモリ・セグメントを分離 (detach) する。 分離する共有メモリ・セグメントは、現在 shmaddr に付加されているものでなければならない。 shmaddr は、それを付加した時に shmat() が返した値に等しくなければならない。
成功した shmdt() コールはその共有メモリ・セグメントに関連する shmid_ds 構造体のメンバーを以下のように更新する:
fork(2) した後、子プロセスは付加された共有メモリ・セグメントを継承する。
exec(2) した後、全ての付加された共有メモリ・セグメントはプロセスから分離される。
exit(2) において、全ての付加された共有メモリ・セグメントはプロセスから分離される。
shmdt() は、成功すると 0 を返す。 エラーの場合、-1 を返し、 errno にエラーの原因を示す値を設定する。
shmdt() が失敗した場合、 EINVAL は以下のようにセットされる:
SVID 3 で (たぶんそれより前だと思うが) shmaddr 引き数の型は char * から const void * に、shmat() の返り値の型は char * から void * に変更された (Linux では libc4 と libc5 のプロトタイプは char * であり、glibc2 のプロトタイプは void * である)。
Linux では共有メモリセグメントに既に削除マークが付けられていても、 その共有メモリセグメントを付加することができる。 しかし POSIX.1-2001 ではこのような動作を指定しておらず、 他の多くの実装もこれをサポートしていない。
以下のシステム・パラメーターは、 shmat() システム・コールに影響する:
現在の実装では、プロセスごとの 共有メモリ・セグメントの最大数 (SHMSEG) に関する実装依存の制限はない。