shmctl(2) System V 共有メモリ (shared memory) を制御する

書式

#include <sys/ipc.h>
#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

説明

shmctl() は、識別子が shmid の System V 共有メモリ・セグメントに対して cmd で指示した制御命令を実行する。

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 構造体は以下のように定義されている (強調されたフィールドは 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 として有効な値は以下の通り:

IPC_STAT
shmid に関連づけられたカーネルデータ構造体の情報を buf で指された shmid_ds 構造体にコピーする。 呼び出し元は共有メモリ・セグメントに対する 読み込み許可を持たなければならない。
IPC_SET
buf によって指される shmid_ds 構造体のいくつかのメンバーの値を、 この共有メモリ・セグメントに関連づけられたカーネルデータ構造体に書き込み、 shm_ctime メンバーも更新する。 以下のフィールドは変更できる。 shm_perm.uid, shm_perm.gid, shm_perm.mode (の最下位 9 ビット)。 呼び出したプロセスの実効 UID が所有者 (shm_perm.uid) または作成者 (shm_perm.cuid) と一致するか、呼び出し元が特権を持たなければならない。
IPC_RMID
セグメントに破棄済みのマークを付ける。 セグメントは、実際には最後プロセスがセグメントを分離した (関連する shmid_ds 構造体の shm_nattch メンバーが 0 になった) 後でのみ破棄される。 呼び出し元はそのセグメントの所有者か作成者であるか、特権を持たなければならない。 buf 引き数は無視される。
セグメントに破棄のマークが付けられると、 関連するデータ構造体において shm_perm.mode フィールドの (標準ではない) SHM_DEST フラグが設定される。 このデータ構造体は IPC_STAT で取得される。
呼び出し元は最終的にはセグメントを忘れずに破棄しなければならない。 そうでなれば、フォールト (fault) されたページは メモリかスワップ (swap) に残り続ける。
proc(5) の /proc/sys/kernel/shm_rmid_forced の説明も参照のこと。
IPC_INFO (Linux 固有)
システム全体での共有メモリの制限とパラメータに関する情報を、 buf が指す構造体に入れて返す。 この構造体は shminfo 型である (そのためキャストが必要である)。 shminfo_GNU_SOURCE 機能検査マクロが定義された場合に <sys/shm.h> で以下のように定義される:
struct  shminfo {
    unsigned long shmmax; /* 最大セグメントサイズ */
    unsigned long shmmin; /* 最小セグメントサイズ。
                             常に 1 */
    unsigned long shmmni; /* 最大セグメント数 */
    unsigned long shmseg; /* プロセスが付加できる
                             セグメントの最大数。
                             カーネル内では未使用 */
    unsigned long shmall; /* 共有メモリの最大ページ数。
                             システム全体での値 */
};
設定 shmmni, shmmax, shmall/proc にある同じ名前のファイル経由で変更可能である。 詳しくは proc(5) を参照。
SHM_INFO (Linux 固有)
共有メモリが消費しているシステム資源に関する情報を 格納した shm_info 構造体を返す。 この構造体は、 _GNU_SOURCE 機能検査マクロが定義された場合に <sys/shm.h> で以下のように定義される:
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 以降では未使用 */
};
SHM_STAT (Linux 固有)
IPC_STAT と同じく shmid_ds 構造体を返す。 但し、 shmid 引き数は、セグメント識別子ではなく、システム上の全ての共有メモリ セグメントに関する情報を管理するカーネルの内部配列へのインデックス である。

呼び出し元は、cmd に以下の値を指定することで、共有メモリ・セグメントが スワップされることを防止したり、許可したりできる:

SHM_LOCK (Linux 固有)
共有メモリ・セグメントをスワップすることを防止する。 ロックが有効になった後、呼び出し元は、 存在することが要求された全てのページをフォールトさせなければならない。 セグメントがロックされると、 関連するデータ構造体において shm_perm.mode フィールドの (標準的ではない) SHM_LOCKED フラグが設定される。 このデータ構造体は IPC_STAT で取得される。
SHM_UNLOCK (Linux 固有)
セグメントのロックを解除し、スワップ・アウトすることを可能にする。

2.6.10 より前のカーネルでは、特権プロセスだけが SHM_LOCKSHM_UNLOCK を利用することができた。 2.6.10 以降のカーネルでは、非特権プロセスであっても次の条件を満たせば これらの操作を利用することができる。その条件とは、プロセスの実効 UID がそのセグメントの所有者もしくは作成者の UID と一致し、 (SHM_LOCK の場合には) ロックするメモリの合計が RLIMIT_MEMLOCK リソース上限 (setrlimit(2) 参照) の範囲内に入っていることである。

返り値

IPC_INFOSHM_INFO 操作は、成功すると、全ての共有メモリセグメントに関する情報を 管理しているカーネルの内部配列の使用中エントリのインデックスの うち最大値を返す (この情報は、システムの全ての共有メモリセグメントに関する情報を 取得するために、 SHM_STAT 操作を繰り返し実行する際に使用できる)。 SHM_STAT 操作は、成功すると、 shmid で指定されたインデックスを持つ共有メモリセグメントの識別子を返す。 他の操作は、成功の場合 0 を返す。

エラーの場合は -1 を返し、 errno を適切に設定する。

エラー

EACCES
IPC_STAT または SHM_STAT が要求され、 shm_perm.modeshmid への読み込みアクセスを許しておらず、 かつ呼び出したプロセスが CAP_IPC_OWNER ケーパビリティ (capability) を持っていない。
EFAULT
cmd 引き数に IPC_SETIPC_STAT が指定されたが buf で指されているアドレスにアクセスできない。
EIDRM
shmid が削除 (remove) された識別子 (identifier) を指している。
EINVAL
shmid が有効な識別子でないか、 cmd が有効なコマンドでない。 もしくは、 SHM_STAT 操作の場合に、 shmid で指定されたインデックス値が現在未使用の配列のスロットを参照していた。
ENOMEM
(2.6.9 以降のカーネルにおいて) SHM_LOCK が指定され、 ロックされる予定のセグメントのサイズ (ロックされる共有メモリ・セグメントの合計バイト数) が、 呼び出したプロセスの実ユーザー ID についての制限を超えた。 この制限は RLIMIT_MEMLOCK ソフト資源制限で定義される (setrlimit(2) を参照)。
EOVERFLOW
IPC_STAT が試みられ、GID や UID の値が buf で指示される構造体に格納するには大き過ぎる。
EPERM
IPC_SETIPC_RMID が試みられ、 呼び出したプロセスの実効ユーザー ID が作成者 (shm_perm.cuid) でも所有者 (shm_perm.uid) でもなく、プロセスが特権を持たない (Linux では CAP_SYS_ADMIN ケーパビリティを持たない)。

または (2.6.9 より前のカーネルで) SHM_LOCK または SHM_UNLOCK が指定されているが、プロセスが特権を持たない (Linux では CAP_IPC_LOCK ケーパビリティを持たない)。 (Linux 2.6.9 以降では、 RLIMIT_MEMLOCK が 0 で呼び出し元が特権を持たない場合にも、このエラーが起こる。)

準拠

SVr4, POSIX.1-2001.

注意

Linux や POSIX の全てのバージョンでは、 <sys/types.h><sys/ipc.h> のインクルードは必要ない。しかしながら、いくつかの古い実装ではこれらのヘッダファイルのインクルードが必要であり、 SVID でもこれらのインクルードをするように記載されている。このような古いシステムへの移植性を意図したアプリケーションではこれらのファイルをインクルードする必要があるかもしれない。

IPC_INFO, SHM_STAT, SHM_INFO 操作は、 ipcs(1) プログラムで割り当て済の資源に関する情報を提供するために 使用されている。将来、これらの操作は変更されたり、 /proc ファイルシステムのインタフェースに移動されるかもしれない。

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 フラグで区別する。

この文書について

この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。