int shmctl(int shmid, int cmd, struct shmid_ds *buf);
buf 引き数は、 shmid_ds 構造体へのポインタである。 この構造体は <sys/shm.h> で以下のように定義されている
struct shmid_ds {
struct ipc_perm shm_perm; /* 所有権と許可 */
size_t shm_segsz; /* セグメントのサイズ (バイト) */
time_t shm_atime; /* 最後の付加 (attach) の時刻 */
time_t shm_dtime; /* 最後の分離 (detach) の時刻 */
time_t shm_ctime; /* 最後に変更が行われた時刻 */
pid_t shm_cpid; /* 作成者 (creator) の PID */
pid_t shm_lpid; /* 最後の shmat(2)/shmdt(2) の PID */
shmatt_t shm_nattch; /* 現在付加されている数 */
...
};
ipc_perm 構造体は <sys/ipc.h> で以下のように定義されている (強調されたフィールドは IPC_SET を使って設定可能である):
struct ipc_perm {
key_t __key; /* shmget(2) に与えられるキー */
uid_t uid; /* 所有者の実効 UID */
gid_t gid; /* 所有者の実効 GID */
uid_t cuid; /* 作成者の実効 UID */
gid_t cgid; /* 作成者の実効 GID */
unsigned short mode; /* 許可 + SHM_DEST と
SHM_LOCKED フラグ */
unsigned short __seq; /* シーケンス番号 */
};
cmd
として有効な値は以下の通り:
呼び出し元は最終的にはセグメントを忘れずに破棄しなければならない。 そうでなれば、フォールト (fault) されたページは メモリかスワップ (swap) に残り続ける。
struct shminfo {
unsigned long shmmax; /* 最大セグメントサイズ */
unsigned long shmmin; /* 最小セグメントサイズ。
常に 1 */
unsigned long shmmni; /* 最大セグメント数 */
unsigned long shmseg; /* プロセスが付加できる
セグメントの最大数。
カーネル内では未使用 */
unsigned long shmall; /* 共有メモリの最大ページ数。
システム全体での値 */
};
設定
shmmni,
shmmax,
shmall
は
/proc
にある同じ名前のファイル経由で変更可能である。
詳しくは
proc(5)
を参照。
struct shm_info {
int used_ids; /* 現在存在するセグメント数 */
unsigned long shm_tot; /* 共有メモリのページ総数 */
unsigned long shm_rss; /* メモリ上にある (スワップされて
いない) 共有メモリページ数 */
unsigned long shm_swp; /* スワップされている共有メモリ
ページ数 */
unsigned long swap_attempts;
/* Linux 2.4 以降では未使用 */
unsigned long swap_successes;
/* Linux 2.4 以降では未使用 */
};
呼び出し元は、cmd に以下の値を指定することで、共有メモリ・セグメントが
スワップされることを防止したり、許可したりできる:
2.6.10 より前のカーネルでは、特権プロセスだけが SHM_LOCK と SHM_UNLOCK を利用することができた。 2.6.10 以降のカーネルでは、非特権プロセスであっても次の条件を満たせば これらの操作を利用することができる。その条件とは、プロセスの実効 UID がそのセグメントの所有者もしくは作成者の UID と一致し、 (SHM_LOCK の場合には) ロックするメモリの合計が RLIMIT_MEMLOCK リソース上限 (setrlimit(2) 参照) の範囲内に入っていることである。
エラーの場合は -1 を返し、 errno を適切に設定する。
IPC_STAT または SHM_STAT が要求され、 shm_perm.mode が shmid への読み込みアクセスを許しておらず、 かつ呼び出したプロセスが CAP_IPC_OWNER ケーパビリティ (capability) を持っていない。
または (2.6.9 より前のカーネルで) SHM_LOCK または SHM_UNLOCK が指定されているが、プロセスが特権を持たない (Linux では CAP_IPC_LOCK ケーパビリティを持たない)。 (Linux 2.6.9 以降では、 RLIMIT_MEMLOCK が 0 で呼び出し元が特権を持たない場合にも、このエラーが起こる。)
Linux では、 shmctl(IPC_RMID) を使ってすでに削除マークがつけられている共有メモリ・セグメントを あるプロセスが付加 (attach) (shmat(2)) することを許可している。 この機能は他の Unix の実装では利用できない。 移植性を考慮したアプリケーションではこれに依存しないようにすべきである。
構造体 shmid_ds 内の多くのフィールドは、 Linux 2.2 では short 型だったが、Linux 2.4 では long 型になった。 この利点を生かすには、glibc-2.1.91 以降の環境下で 再コンパイルすれば十分である。 カーネルは新しい形式の呼び出しと古い形式の呼び出しを cmd 内の IPC_64 フラグで区別する。