SEMCTL(2)

名前
semctl - System V セマフォの制御操作を行なう

書式
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semctl(int semid, int semnum, int cmd, ...);

説明
semctl() は、 semid で指定された System V セマフォ集合 (semaphore set) またはセマフォ集合の semnun 番目のセマフォに対して、 cmd で指定された制御操作を行なう (集合内のセマフォの番号は 0 から始まる)。

この関数は、 cmd の値に依存して、3 個または 4 個の引き数を持つ。 引き数が 4 個の場合、第 4 引き数の型は union semun である。 呼び出し元プログラムは、 この共用体 (union) を以下のように定義しなければならない。
union semun {
    int              val;    /* SETVAL の値 */
    struct semid_ds *buf;    /* IPC_STAT, IPC_SET 用のバッファ */
    unsigned short  *array;  /* GETALL, SETALL 用の配列 */
    struct seminfo  *__buf;  /* IPC_INFO 用のバッファ
                                (Linux 固有) */
};

semid_ds データ構造体は <sys/sem.h> で以下のように定義されている:
struct semid_ds {
    struct ipc_perm sem_perm;  /* 所有権と許可 */
    time_t          sem_otime; /* 最後の semop の時刻 */
    time_t          sem_ctime; /* 最後に変更が行われた時刻 */
    unsigned long   sem_nsems; /* 集合内のセマフォの数 */
};

ipc_perm 構造体は以下のように定義されている (強調されたフィールドは IPC_SET を使って設定可能である):

struct ipc_perm {
    key_t          __key; /* semget(2) に与えられるキー */
    uid_t          uid;   /* 所有者 (owner) の実効 UID */
    gid_t          gid;   /* 所有者の実効 GID */
    uid_t          cuid;  /* 作成者 (creator) の実効 UID */
    gid_t          cgid;  /* 作成者の実効 GID */
    unsigned short mode;  /* 許可 */
    unsigned short __seq; /* シーケンス番号 */
};

cmd として有効な値は次の通りである。

IPC_STAT
    semid に関連づけられたカーネルデータ構造体の情報を arg.buf で指された semid_ds 構造体へコピーする。 semnum 引き数は無視される。 呼び出したプロセスはそのセマフォ集合に対する 読み込み許可を持たなければならない。

IPC_SET
    arg.buf で指定された semid_ds 構造体のメンバーのいくつかの値を、 このセマフォに関連づけられたカーネルデータ構造体に書き込み、 sem_ctime メンバーの値も更新する。 構造体の以下のメンバーが更新される: sem_perm.uid, sem_perm.gid, sem_perm.mode (の最下位 9 ビット)。 呼び出したプロセスの実効 UID が所有者 (sem_perm.uid) または作成者 (sem_perm.cuid) と一致するか、呼び出した人が特権を持たなければならない。 semnum 引き数は無視される。

IPC_RMID
    セマフォ集合をただちに削除し、その集合上の semop(2) コールでブロックされている全てのプロセスを目覚めさせる (エラー値が返されて、 errno に EIDRM が設定される)。 呼び出したプロセスの実効ユーザ ID が そのセマフォ集合の作成者または所有者と一致するか、 呼び出した人が特権を持たなければならない。 semnum 引き数は無視される。

IPC_INFO (Linux 固有)
    システム全体でのセマフォの制限とパラメータに関する情報を、 arg.__buf が指す構造体に入れて返す。 この構造体は seminfo 型である。 seminfo は _GNU_SOURCE 機能検査マクロが定義された場合に <sys/sem.h> で以下のように定義される:
    struct  seminfo {
        int semmap;  /* セマフォ・マップの最大エントリ数;
                        カーネル内では未使用 */
        int semmni;  /* セマフォ集合の最大数 */
        int semmns;  /* 全セマフォ集合中のセマフォの
                        最大数 */
        int semmnu;  /* アンドゥ構造体のシステム全体での
                        最大数; カーネル内では未使用 */
        int semmsl;  /* 一つのセマフォ集合の最大セマフォ数 */
        int semopm;  /* semop(2) に渡す操作の最大数 */
        int semume;  /* プロセスあたりのアンドゥ・エントリ
                        の最大数; カーネル内では未使用 */
        int semusz;  /* 構造体 sem_undo のサイズ */
        int semvmx;  /* セマフォの最大値 */
        int semaem;  /* セマフォの調整 (semaphore adjustment;
                         SEM_UNDO) のために記録される最大値 */
    };
    設定 semmsl, semmns, semopm, semmni は /proc/sys/kernel/sem 経由で変更可能である。 詳しくは proc(5) を参照。

SEM_INFO (Linux 固有)
    IPC_INFO のときと同じ情報を格納した seminfo 構造体を返す。 但し、以下のフィールドにはセマフォが消費しているシステム資源に 関する情報が格納される点が異なる。 semusz フィールドは現在システム上に存在するセマフォ集合の数を返す。 semaem フィールドはシステム上の全てのセマフォ集合に含まれる セマフォの総数を返す。

SEM_STAT (Linux 固有)
    IPC_STAT と同じく semid_ds 構造体を返す。 但し、 semid 引き数は、セマフォ識別子ではなく、システム上の全てのセマフォ集合 に関する情報を管理するカーネルの内部配列へのインデックスである。

GETALL
    集合の全てのセマフォの semval の値 (現在の値) を arg.array に返す。 semnum 引き数は無視される。 呼び出したプロセスはそのセマフォ集合に読み込み許可を持たなければならない。

GETNCNT
    システムコールは集合の semnum 番目のセマフォの semncnt の値を返す (集合の semnum 番目のセマフォの semval の増加を待っているプロセスの数を返す)。 呼び出したプロセスはそのセマフォ集合に読み込み許可を持たなければならない。

GETPID
    システムコールは集合の semnum 番目のセマフォの sempid の値 (集合の semnum 番目のセマフォに最後に semop(2) コールを実行したプロセスの PID) を返す。 呼び出したプロセスはそのセマフォ集合に読み込み許可を持たなければならない。

GETVAL
    システムコールは集合の semnum 番目のセマフォの semval の値を返す。 呼び出したプロセスはそのセマフォ集合に読み込み許可を持たなければならない。

GETZCNT
    システムコールは集合の semnum 番目のセマフォの semzcnt の値を返す (集合の semnum 番目のセマフォの semval の値が 0 になるのを待っているプロセスの数を返す)。 呼び出したプロセスはそのセマフォ集合に読み込み許可を持たなければならない。

SETALL
    集合の全てのセマフォの semval に arg.array で指定された値を設定する。 その集合に関連する semid_ds 構造体の sem_ctime メンバーの値も更新する。 全てのプロセスのセマフォの変更についてのアンドゥ・エントリ (semop(2) を参照) は消去 (clear) される。 セマフォの値の変更により、他のプロセス内でブロックされている semop(2) コールの続行が許可されると、それらのプロセスは起こされる (wake up)。 semnum 引き数は無視される。 呼び出したプロセスはそのセマフォ集合に 変更 (書き込み) 許可を持たなければならない。

SETVAL
    集合の semnum 番目のセマフォの semval に arg.val の値を設定する。その集合に関連する semid_ds 構造体の sem_ctime メンバーの値も更新する。 全てのプロセスのセマフォの変更についてのアンドゥ・エントリは消去される。 セマフォの値の変更により、他のプロセス内でブロックされている semop(2) コールの続行が許可されると、それらのプロセスは起こされる (wake up)。 呼び出したプロセスはそのセマフォ集合に 変更 (書き込み) 許可を持たなければならない。

返り値
失敗した場合、 semctl() は -1 を返し、 errno にそのエラーを示す。 そうでなければシステムコールは cmd によって以下の負でない値を返す:

GETNCNT
    semncnt の値

GETPID
    sempid の値

GETVAL
    semval の値

GETZCNT
    semzcnt の値

IPC_INFO
    全てのセマフォ集合に関する情報を管理しているカーネルの内部配列の使用中 エントリのインデックスの最大値 (この情報は、システムの全てのセマフォ集合に関する情報を取得するために SEM_STAT 操作を繰り返し実行する際に使用できる)

SEM_INFO
    IPC_INFO と同じ

SEM_STAT
    semid で指定されたインデックスを持つセマフォ集合の識別子

cmd の値がそれ以外の場合、成功すると 0 が返される。

エラー
失敗した場合は errno には以下の値のどれかが設定される:

EACCES
    cmd 引き数が GETALL, GETPID, GETVAL, GETNCNT, GETZCNT, IPC_STAT, SEM_STAT, SETALL, SETVAL のうちの何れかの値を持ち、 呼び出したプロセスがセマフォに対して必要とされる許可と CAP_IPC_OWNER ケーパビリティ (capability) を持っていない。

EFAULT
    arg.buf または arg.array で指されているアドレスにアクセスすることができない。

EIDRM
    セマフォ集合が削除された。

EINVAL
    cmd または semid に無効な値が指定された。 もしくは、 SEM_STAT 操作の場合に、 semid で指定されたインデックス値が現在未使用の配列のスロットを参照いていた。

EPERM
    cmd 引き数に IPC_SET または IPC_RMID が指定され、呼び出したプロセスの実効ユーザ ID がセマフォの (sem_perm.cuid で見つかる) 作成者または (sem_perm.uid で見つかる) 所有者でもなく、 プロセスが CAP_SYS_ADMIN ケーパビリティを持たない。

ERANGE
    cmd 引き数に SETALL または SETVAL が指定され、(集合のセマフォのどれかの) semval に設定される値が 0 より小さいか、実装の制限 SEMVMX よりも大きい。

準拠
SVr4, POSIX.1-2001. POSIX.1-2001 では semid_ds 構造体の sem_nsems フィールドは unsigned short 型を持つと規定されており、 他のほとんどのシステムでこのフィールドは unsigned short 型になっている。 Linux 2.4 以前ではそうなっていたが、 Linux 2.4 以降ではこのフィールドは unsigned long 型である。

注意
Linux や POSIX の全てのバージョンでは、 <sys/types.h> と <sys/ipc.h> のインクルードは必要ない。しかしながら、いくつかの古い実装ではこれらのヘッダファイルのインクルードが必要であり、 SVID でもこれらのインクルードをするように記載されている。このような古いシステムへの移植性を意図したアプリケーションではこれらのファイルをインクルードする必要があるかもしれない。 IPC_INFO, SEM_STAT, SEM_INFO 操作は ipcs(1) プログラムによって割当られた資源について情報を提供するために使用される。 将来的にはこれらは変更されるか、 /proc ファイル・システム・インタフェースに移動されるかもしれない。

構造体 semid_ds 内の多くのフィールドは、 Linux 2.2 では short 型だったが、Linux 2.4 では long 型になった。 この利点を生かすには、glibc-2.1.91 以降の環境下で 再コンパイルすれば十分である。 カーネルは新しい形式の呼び出しと古い形式の呼び出しを cmd 内の IPC_64 フラグで区別する。

初期のバージョンの glibc では、 semun 共用体は <sys/sem.h> で定義されていたが、 POSIX.1-2001 では呼び出し側がこの共用体を定義する必要がある。 この共用体が定義されていない glibc のバージョンでは、 マクロ _SEM_SEMUN_UNDEFINED が <sys/sem.h> で定義されている。

以下は semctl() コールに影響するセマフォ集合のシステム制限:

SEMVMX
    semval の最大値 : 実装依存 (32767)。

移植性を高めるための一番良い方法は、常に 4 個の引き数で semctl() を呼び出すことである。

関連項目
ipc(2), semget(2), semop(2), capabilities(7), sem_overview(7), svipc(7)

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