SHMCTL(2)

名前
shmctl - 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;   /* 作成時刻 / shmctl() による
                                        最後の変更時刻 */
        pid_t           shm_cpid;    /* 作成者 (creator) の PID */
        pid_t           shm_lpid;    /* 最後の shmat(2)/shmdt(2) の PID */
        shmatt_t        shm_nattch;  /* 現在付加されている数 */
        ...
    };

shmid_ds 構造体のフィールドは以下の通りである。

shm_perm
    This is an ipc_perm structure (see below) that specifies the access permissions on the shared memory segment.

shm_segsz
    共有メモリーセグメントのサイズ (バイト単位)。

shm_atime
    Time of the last shmat(2) system call that attached this segment.

shm_dtime
    Time of the last shmdt(2) system call that detached tgis segment.

shm_ctime
    Time of creation of segment or time of the last shmctl() IPC_SET operation.

shm_cpid
    その共有メモリーセグメントを作成したプロセスの ID。

shm_lpid
    ID of the last process that executed a shmat(2) or shmdt(2) system call on this segment.

shm_nattch
    Number of processes that have this segment attached.

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;    /* シーケンス番号 */
    };

The least significant 9 bits of the mode field of the ipc_perm structure define the access permissions for the shared memory segment. The permission bits are as follows:
0400 | Read by user
0200 | Write by user
0040 | Read by group
0020 | Write by group
0004 | Read by others
0002 | Write by others

Bits 0100, 0010, and 0001 (the execute bits) are unused by the system. (It is not necessary to have execute permission on a segment in order to perform a shmat(2) call with the SHM_EXEC flag.)

cmd として有効な値は以下の通り:

IPC_STAT
    shmid に関連づけられたカーネルデータ構造体の情報を buf で指された shmid_ds 構造体にコピーする。 呼び出し元は共有メモリーセグメントに対する 読み込み許可を持たなければならない。

IPC_SET
    Write the values of some members of the shmid_ds structure pointed to by buf to the kernel data structure associated with this shared memory segment, updating also its shm_ctime member.

    以下のフィールドが更新される: shm_perm.uid, shm_perm.gid および shm_perm.mode (の下位 9 ビット)。

    The effective UID of the calling process must match the owner (shm_perm.uid) or creator (shm_perm.cuid) of the shared memory segment, or the caller must be privileged.

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 引数は、セグメント識別子ではなく、システム上の全ての共有メモリー セグメントに関する情報を管理するカーネルの内部配列へのインデックス である。

SHM_STAT_ANY (Linux-specific, Linux 4.17 以降)
    Return a shmid_ds structure as for SHM_STAT. However, shm_perm.mode is not checked for read access for shmid, meaning that any user can employ this operation (just as any user may read /proc/sysvipc/shm to obtain the same information).

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

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

SHM_UNLOCK (Linux 固有)
    セグメントのロックを解除し、スワップアウトすることを可能にする。

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

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

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

エラー

EACCES
    IPC_STAT or SHM_STAT is requested and shm_perm.mode does not allow read access for shmid, and the calling process does not have the CAP_IPC_OWNER capability in the user namespace that governs its IPC namespace.

EFAULT
    cmd 引数に IPC_SET か IPC_STAT が指定されたが buf で指されているアドレスにアクセスできない。

EIDRM
    shmid が削除 (remove) された識別子 (identifier) を指している。

EINVAL
    shmid が有効な識別子でないか、 cmd が有効なコマンドでない。 もしくは、操作 SHM_STAT か SHM_STAT_ANY の場合に、 shmid で指定されたインデックス値が現在未使用の配列のスロットを参照していた。

ENOMEM
    (2.6.9 以降のカーネルにおいて) SHM_LOCK が指定され、 ロックされる予定のセグメントのサイズ (ロックされる共有メモリーセグメントの合計バイト数) が、 呼び出したプロセスの実ユーザー ID についての制限を超えた。 この制限は RLIMIT_MEMLOCK ソフト資源制限で定義される (setrlimit(2) を参照)。

EOVERFLOW
    IPC_STAT が試みられ、GID や UID の値が buf で指示される構造体に格納するには大き過ぎる。

EPERM
    IPC_SET か IPC_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 で呼び出し元が特権を持たない場合にも、このエラーが起こる。)

準拠
POSIX.1-2001, POSIX.1-2008, SVr4.

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

関連項目
mlock(2), setrlimit(2), shmget(2), shmop(2), capabilities(7), sysvipc(7)

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