other versions
other sections
SEMOP(2) | Linux Programmer's Manual | SEMOP(2) |
名前¶
semop, semtimedop - セマフォの操作書式¶
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>int semop(int semid, struct sembuf *sops, unsigned nsops);int semtimedop(int semid, struct sembuf *sops, unsigned nsops, struct timespec *timeout);
glibc 向けの機能検査マクロの要件 ( feature_test_macros(7) 参照):
説明¶
セマフォ集合 (semaphore set) のメンバーの各セマフォは 以下の関連情報を持っている:unsigned short semval; /* セマフォ値 */ unsigned short semzcnt; /* ゼロを待つプロセス数 */ unsigned short semncnt; /* 増加を待つプロセス数 */ pid_t sempid; /* 最後に操作を行なったプロセス */semop() は semid で指定されたセマフォ集合の選択されたセマフォに対して操作を行う。 sops は nsops 個の要素の配列を指し、配列の各要素は個々のセマフォに 対する操作を示す。その型は struct sembuf で、次のメンバを持つ:
unsigned short sem_num; /* セマフォ番号 */ short sem_op; /* セマフォ操作 */ short sem_flg; /* 操作フラグ */sem_flg には IPC_NOWAIT と SEM_UNDO が設定できる。 SEM_UNDO が指定された操作は、そのプロセスが終了した時に自動的に取り消される。 sops に含まれる操作の集合は、 配列の順序 で、 アトミックに 実行される。 すなわち、全ての操作が完全に実行されるか、全く実行されないかの どちらかとなる。 全ての操作が直ちに実行できない場合のこのシステムコールの振る舞いは 個々の操作の sem_flg フィールドに IPC_NOWAIT が存在するかによって決まり、後述のようになる。
- •
- semval が 0 になった: このとき semzcnt の値は 1 減算される。
- •
- セマフォ集合が削除された: このとき semop() は失敗し、 errno に EIDRM が設定される。
- •
- 呼び出し元プロセスがシグナルを捕獲した: このとき semzcnt の値は 1 減算され、 semop() は失敗し errno に EINTR が設定される。
- •
- semtimedop() の timeout で指定された制限時間が経過した: このとき semtimedop() は失敗し、 errno に EAGAIN が設定される。
- •
- semval が sem_op の絶対値以上になった: このとき semncnt が 1 減算され、 semval から sem_op の絶対値が引かれる。 この操作に SEM_UNDO が指定されていた場合にはこのセマフォのプロセス・アンドゥ数 ( semadj) も更新する。
- •
- セマフォ集合がシステムから削除された: このとき semop() は失敗し errno に EIDRM が設定される。
- •
- 呼び出したプロセスがシグナルを捕獲した: このとき semncnt が 1 減算され、 semop() は失敗し errno に EINTR が設定される。
- •
- semtimedop() の timeout で指定された制限時間が経過した: このとき semtimedop() は失敗し、 errno に EAGAIN が設定される。
返り値¶
成功した場合、 semop() と semtimedop() は 0 を返す。そうでなければ -1 を返し、 エラーを示す errno を設定する。エラー¶
失敗した場合、 errno に以下のどれかが設定される:- E2BIG
- nsops 引き数が SEMOPM より大きい。 SEMOPM は一回のシステムコールで許される操作の最大個数である。
- EACCES
- 呼び出し元プロセスには指定されたセマフォ操作を行うのに 必要なアクセス許可がなく、 CAP_IPC_OWNER ケーパビリティもない。
- EAGAIN
- 操作を直ちに処理することができず、かつ sem_flg に IPC_NOWAIT が指定されているか timeout で指定された制限時間が経過した。
- EFAULT
- 引き数 sops か timeout が指しているアドレスにアクセスできない。
- EFBIG
- ある操作で、 sem_num の値が 0 未満か、集合内のセマフォの数以上である。
- EIDRM
- セマフォ集合が削除された。
- EINTR
- このシステムコールで停止している時にプロセスがシグナルを捕獲した。 single(7) 参照。
- EINVAL
- セマフォ集合が存在しないか、 semid が 0 未満であるか、 nsops が正の数でない。
- ENOMEM
- ある操作で sem_flg に SEM_UNDO が指定されたが、システムにアンドゥ構造体に割り当てる十分なメモリがない。
- ERANGE
- ある操作で sem_op+semval が SEMVMX より大きい。 SEMVMX は semval の最大値で、その値は実装依存である。
バージョン¶
semtimedop() は Linux 2.5.52 で初めて登場し、 それからカーネル 2.4.22 にも移植された。 semtimedop() の glibc でのサポートはバージョン 2.3.3 で初めて登場した。準拠¶
SVr4, POSIX.1-2001.注意¶
あるプロセスの sem_undo 構造体は fork(2) で生成された子プロセスには継承されないが、 execve(2) システムコールの場合は継承される。 semop() はシグナルハンドラによって中断された後に、 決して自動的に再開することはない。 たとえシグナルハンドラの設定時に SA_RESTART フラグがセットされていても再開することはない semadj はプロセスごとの整数で、 SEM_UNDO フラグを設定して実行された全てのセマフォ操作の(負数の)カウンタである。 semctl(2) に SETVAL または SETALL を指定し、セマフォの値が 直接設定された場合には、全てのプロセスにおいて対応する semadj の値がクリアされる。 あるセマフォの semval, sempid, semzcnt, semnct の値はいずれも、適切な操作を指定して semctl(2) を呼び出すことで取得できる。 セマフォ集合のリソースに関する制限のうち、 semop() に影響を及ぼすものを以下に挙げる:- SEMOPM
- 一回の semop() で許される操作の最大数 (32)。 (Linux では、この制限値は /proc/sys/kernel/sem の第3フィールドに対応し、読み出しも変更もできる)。
- SEMVMX
- semval が取り得る最大値: 実装依存 (32767)。
バグ¶
プロセスが終了する際、プロセスに対応する semadj の集合を使って、 SEM_UNDO フラグ付きで実行された全てのセマフォ操作の影響を取り消す。 これによりある問題が発生する: これらのセマフォの調整を行っていると、 中にはセマフォの値が 0 未満の値にしようとする場合が出てくる。 このような場合、どのように実装するべきか? ひとつの考えられる手法は、全てのセマフォ調整が実行されるまで 停止することである。しかし、この方法ではプロセスの終了が 長時間にわたって停止されることがあるので望ましくない。 しかもどれくらい長時間になるかは分からない。 別の選択肢として、このようなセマフォ調整を完全に無視してしまう方法がある (これはセマフォ操作として IPC_NOWAIT が指定するのと少し似ている)。 Linux は第三の手法を採用している: セマフォの値を出来るだけ (つまり 0 まで) 減少させて、プロセスの終了を直ちに続行できるようにしている。例¶
以下の部分的なコードは、 セマフォ 0 の値が 0 になるのを待ってから、 セマフォの値を 1 加算する処理を、 semop() を使ってアトミック (atomically) に行う。struct sembuf sops[2]; int semid; /* Code to set semid omitted */ sops[0].sem_num = 0; /* Operate on semaphore 0 */ sops[0].sem_op = 0; /* Wait for value to equal 0 */ sops[0].sem_flg = 0; sops[1].sem_num = 0; /* Operate on semaphore 0 */ sops[1].sem_op = 1; /* Increment value by one */ sops[1].sem_flg = 0; if (semop(semid, sops, 2) == -1) { perror("semop"); exit(EXIT_FAILURE); }
関連項目¶
semctl(2), semget(2), sigaction(2), capabilities(7), sem_overview(7), svipc(7), time(7)この文書について¶
この man ページは Linux man-pages プロジェクトのリリース 3.41 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2012-05-10 | Linux |