SEMOP(2)

名前
semop - セマフォー(semaphore)の操作

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

int semop ( int semid, struct sembuf *sops, unsigned nsops )

説明
この関数は semid で指定されたセマフォー集合(semaphore set)のメンバーを操作する。 sops によって指される sembuf 構造体の nsops 個の要素を持つ配列はセマフォーに対する操作を指定する。 sembuf 構造体 は以下のメンバーを含んでいる:

    short sem_num; /* semaphore number: 0 = first */
    short sem_op; /* semaphore operation */
    short sem_flg; /* operation flags */

sem_flg には IPC_NOWAIT と SEM_UNDO が設定できる。 SEM_UNDO が指定された操作はそのプロセス(process)が終了(exit)した時点で もとに戻される。

このシステム・コール(system call)はその操作の全てが 成功する場合に、そしてその場合にのみ実行されることを保証する。 それぞれの操作はセマフォー集合の sem_num番目 のセマフォーに対して実行される。- セマフォー集合の最初はセマフォー 0 である。 - そして操作は以下の三つの中のどれかである。

もし sem_op が正の数ならば、操作としてその値を semval に加える。さらにこの操作に SEM_UNDO が指定されている場合は、システムはこのセマフォーの プロセス・アンドゥ数 (process undo count)を更新する。 操作は常に通過し、プロセスの停止(sleep)は起こらない。 呼び出したプロセスはそのセマフォー集合を変更する許可がなければならない。

もし sem_op がゼロならば、プロセスはそのセマフォー集合に対する読み込みの許可を持たな ければならない。 もし semval がゼロならば、操作は通過する。そうでなく sem_flg に IPC_NOWAIT が指定されていればシステム・コールは失敗し(それ以前の全ての処理をもとに 戻して)、 errno に EAGAIN を設定する。そうでなければ semzcnt を 1 増加させて、以下の状況が起こるまでプロセスを停止(sleep)する:

    •   semval が 0 になる、その時に semzcnt は 1 減少する。

    •   セマフォー集合が削除される: システム・コールが失敗し、 errno に EIDRM が設定される。

    •   呼び出したプロセスが捕獲(catch)するべきシグナル(signal)を受ける: semzcnt の値が 1 減少し、システム・コールは失敗し、 errno に EINTR が設定される。

もし sem_op がゼロ未満ならば、プロセスはそのセマフォー集合を変更する許可が必要である。 semval が sem_op の絶対値と等しいか大きい場合は、 semval から sem_op の絶対値を引く。 さらに、この操作に SEM_UNDO が指定されている場合は、このセマフォーのプロセス・アンドゥ数を更新する。 それから操作は通過する。 そうでなく sem_flg に IPC_NOWAIT が指定された場合は、システム・コールは失敗し(それ以前の全ての処理をもとに 戻して)、 errno に EAGAIN を設定する。そうでなければ semncnt を 1 増加させて、以下のどれかが起こるまでプロセスを停止(sleep)する:

    •   semval が sem_op の絶対値と等しいか大きい、この時 semncnt が 1減少し、 semval から sem_op の絶対値が引かれる。この操作に SEM_UNDO が指定された場合にはこのセマフォーのプロセス・アンドゥ数を更新する。

    •   セマフォー集合がシステムから削除された: システム・コールは失敗し errno に EIDRM が設定される。

    •   呼び出したプロセスが捕獲(catch)すべきシグナル(signal)を受ける: semncnt の値が 1 減少し、システム・コールは失敗し、 errno に EINTR が設定される。

成功した場合、 sops によって指された配列で指定されたセマフォーの sem 構造体の sempid メンバーには呼び出したプロセスのプロセス ID が設定される。 さらに sem_otime と sem_ctime の両方に現在時刻が設定される。

返り値
成功した場合はシステム・コールは 0 を返す。そうでなければ -1 を返し、 errno にそのエラーを示す。

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

E2BIG
    nsops 引き数が SEMOPM より大きい、 SEMOPM は一回のシステム・コールで許される操作の最大回数。

EACCES
    呼び出したプロセスがそのセマフォー集合に指定された操作を行なうのに 必要なアクセス許可を持っていない。

EAGAIN
    操作が通過できず、 sem_flg に IPC_NOWAIT が指定されている。

EFAULT
    sops で指されているアドレスにアクセスできない。

EFBIG
    ある操作で、 sem_num の値が 0 未満であるか集合内のセマフォーの数以上である。

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

EINTR
    待ちキュー(queue)で停止している時にプロセスが捕獲すべきシグナルを受けた。

EINVAL
    セマフォー集合が存在しない、または semid が 0未満、または nsops が正の数でない。

ENOMEM
    ある操作で sem_flg に SEM_UNDO が指定されたが、システムにアンドゥ構造体に割り当てる十分なメモリがない。

ERANGE
    ある操作で semop+semval が SEMVMX より大きい。 SEMVMX は実装依存の semval の最大値。

注意
プロセスの sem_undo 構造体は fork(2) システム・コールの実行に際して子プロセスには継承されない。 execve(2) システム・コールの実行の場合は入れ代ったプロセスに継承される。

以下が semop コールに関連するセマフォー集合の資源の制限である:

SEMOPM
    一回の semop コールで許される操作の最大数: 方針依存。

SEMVMX
    semval に与えられる最大値: 実装依存(32767)。

Linux における 実装では以下のものにシステム固有の制限はない。 終了時の修正(adjust on exit)の最大値 (SEMAEM)、 システム全体のアンドゥ構造体の最大数 (SEMMNU)、 プロセスあたりのアンドゥ構造体の最大数。

バグ
システムはプロセスごとの sem_undo 構造体をアンドゥ要求付きで変更されたセマフォーごとに保持している。 これらの構造体はプロセスが終了(exit)した時に解放(free)される。 このアンドゥ機構で不幸なことの一つはセマフォーの配列へ分解不能(atomic)の 操作の組を使うという概念にふさわしくないことである。 配列とその中の各セマフォーへのアンドゥ要求は多くの semop コールの累積となっているかもしれない。 終了する時にプロセスは停止(sleep)するべきか、それとも 全てのアンドゥ操作に対して IPC_NOWAIT フラグの効果を適用すべきか？ 今のところ、これらのアンドゥ操作 はただちに適用され、待ちを要求するような操作は黙って無視される。 このように、無害なアンドゥの使用は私的(private)なセマフォーでのみ保証される。

準拠
SVr4, SVID. SVr4 には他に EINVAL, EFBIG, ENOSPC のエラー状態についての 記述がある。

関連項目
ipc(5), semctl(2), semget(2).