Manpages

名 前

semop, semtimedop − System V セ マ フ ォ の 操 作

書 式

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

int semop(int semid, struct sembuf *sops, size_t nsops);

int semtimedop(int semid, struct sembuf *sops, size_t nsops,
const struct timespec *
timeout);

glibc 向 け の 機 能 検 査 マ ク ロ の 要 件 (feature_test_macros(7) 参 照 ):

semtimedop(): _GNU_SOURCE

説 明

System V セ マ フ ォ 集 合 (semaphore set) の メ ン バ ー の 各 セ マ フ ォ は 以 下 の 関 連 情 報 を 持 っ て い る :

unsigned short semval; /* セ マ フ ォ 値 */
unsigned short semzcnt; /* ゼ ロ を 待 つ プ ロ セ ス 数 */
unsigned short semncnt; /* 増 加 を 待 つ プ ロ セ ス 数 */
pid_t sempid; /* 最 後 に 操 作 を 行 な っ た プ ロ セ ス の ID */

semop() は semid で 指 定 さ れ た セ マ フ ォ 集 合 の 選 択 さ れ た セ マ フ ォ に 対 し て 操 作 を 行 う 。 sopsnsops 個 の 要 素 の 配 列 を 指 し 、 配 列 の 各 要 素 は 個 々 の セ マ フ ォ に 対 す る 操 作 を 示 す 構 造 体 で あ る 。 そ の 型 は struct sembuf で 、 次 の メ ン バ を 持 つ :

unsigned short sem_num; /* セ マ フ ォ 番 号 */
short sem_op; /* セ マ フ ォ 操 作 */
short sem_flg; /* 操 作 フ ラ グ */

sem_flg に は IPC_NOWAITSEM_UNDO が 設 定 で き る 。 SEM_UNDO が 指 定 さ れ た 操 作 は 、 そ の プ ロ セ ス が 終 了 し た 時 に 自 動 的 に 取 り 消 さ れ る 。

sops に 含 ま れ る 操 作 の 集 合 は 、 配 列 の 順 序 で 、 ア ト ミ ッ ク に 実 行 さ れ る 。 す な わ ち 、 全 て の 操 作 が 完 全 に 実 行 さ れ る か 、 全 く 実 行 さ れ な い か の ど ち ら か と な る 。 全 て の 操 作 が 直 ち に 実 行 で き な い 場 合 の こ の シ ス テ ム コ ー ル の 振 る 舞 い は 個 々 の 操 作 の sem_flg フ ィ ー ル ド に IPC_NOWAIT が 存 在 す る か に よ っ て 決 ま り 、 後 述 の よ う に な る 。 そ れ ぞ れ の 操 作 は セ マ フ ォ 集 合 の sem_num番 目 の セ マ フ ォ に 対 し て 実 行 さ れ る 。 セ マ フ ォ 集 合 の 最 初 の セ マ フ ォ に は 番 号 0 が 振 ら れ る 。 そ し て 操 作 は 三 種 類 あ り 、 sem_op の 値 で 区 別 さ れ る 。

sem_op が 正 の 整 数 の 場 合 、 そ の 値 を セ マ フ ォ の 値 (semval) に 加 算 す る 。 さ ら に 、 こ の 操 作 で SEM_UNDO が 指 定 さ れ て い た 場 合 は 、 シ ス テ ム は こ の セ マ フ ォ の の 調 整 値 (semadj) か ら 値 sem_op を 減 算 す る 。 こ の 操 作 は 必 ず 実 行 で き 、 ス レ ッ ド の 停 止 は 起 こ ら な い 。 呼 び 出 し 元 プ ロ セ ス は 対 象 の セ マ フ ォ 集 合 を 変 更 す る 許 可 が な け れ ば な ら な い 。

sem_op が 0 の 場 合 、 「 ゼ ロ ま で 待 つ 」 操 作 で あ る 。 こ の 場 合 、 プ ロ セ ス は そ の セ マ フ ォ 集 合 に 対 す る 読 み 込 み 許 可 が な け れ ば な ら な い 。 semval が 0 な ら ば 、 操 作 は 直 ち に 行 わ れ る 。 semval が 0 で な い 場 合 、 sem_flgIPC_NOWAIT が 指 定 さ れ て い れ ば 、 semop() は 失 敗 し 、 errnoEAGAIN が 設 定 さ れ る (こ の と き sops に 対 す る 操 作 は 全 く 実 行 さ れ な い )。 sem_flgIPC_NOWAIT が 指 定 さ れ て い な い 場 合 、 semzcnt (セ マ フ ォ 値 が 0 に な る の を 待 っ て い る ス レ ッ ド の 数 ) を 1 増 加 さ せ て 、 以 下 の い ず れ か が 起 こ る ま で ス レ ッ ド を 停 止 (sleep) す る 。

semval が 0 に な っ た : こ の と き semzcnt の 値 は 1 減 算 さ れ る 。

セ マ フ ォ 集 合 が 削 除 さ れ た : こ の と き semop() は 失 敗 し 、 errnoEIDRM が 設 定 さ れ る 。

呼 び 出 し 元 ス レ ッ ド が シ グ ナ ル を 捕 獲 し た : こ の と き semzcnt の 値 は 1 減 算 さ れ 、 semop() は 失 敗 し errnoEINTR が 設 定 さ れ る 。

sem_op が 0 未 満 の 場 合 、 プ ロ セ ス に は そ の セ マ フ ォ 集 合 を 変 更 す る 許 可 が な け れ ば な ら な い 。 semvalsem_op の 絶 対 値 以 上 の 場 合 は 、 操 作 は 直 ち に 実 行 さ れ る : semval か ら sem_op の 絶 対 値 を 減 算 し 、 さ ら に 、 こ の 操 作 に SEM_UNDO が 指 定 さ れ て い る 場 合 は 、 こ の セ マ フ ォ の 調 整 値 (semadj) に sem_op の 絶 対 値 を 加 算 す る 。 semvalsem_op の 絶 対 値 よ り 小 さ く 、 sem_flgIPC_NOWAIT が 指 定 さ れ た 場 合 は 、 semop() は 失 敗 し 、 errnoEAGAIN が 設 定 さ れ る (こ の と き sops の 操 作 は 全 く 実 行 さ れ な い )。 semvalsem_op の 絶 対 値 よ り 小 さ く 、 IPC_WAIT が 指 定 さ れ て い な い 場 合 は 、 semncnt (こ の セ マ フ ォ の 値 が 増 加 す る の を 待 っ て い る ス レ ッ ド 数 の カ ウ ン タ ー ) を 1 増 加 さ せ て 、 以 下 の い ず れ か が 起 こ る ま で ス レ ッ ド を 停 止 (sleep) す る 。

semvalsem_op の 絶 対 値 以 上 に な っ た 。 こ の 時 点 で 、 操 作 は 上 述 の 通 り 実 行 さ れ る 。

セ マ フ ォ 集 合 が シ ス テ ム か ら 削 除 さ れ た : こ の と き semop() は 失 敗 し errnoEIDRM が 設 定 さ れ る 。

呼 び 出 し た ス レ ッ ド が シ グ ナ ル を 捕 獲 し た : こ の と き semncnt が 1 減 算 さ れ 、 semop() は 失 敗 し errnoEINTR が 設 定 さ れ る 。 操 作 が 成 功 し た 場 合 、 sops が 指 す 配 列 に よ っ て 操 作 対 象 と な っ た 各 セ マ フ ォ の sempid メ ン バ ー に は 呼 び 出 し 元 の プ ロ セ ス ID が 設 定 さ れ る 。 さ ら に sem_otime に 現 在 時 刻 が 設 定 さ れ る 。

semtimedop()
semtimedop
() 関 数 の 振 る 舞 い は semop() と 全 く 同 じ だ が 、 呼 び 出 し 元 ス レ ッ ド が 停 止 す る 場 合 、 停 止 期 間 の 上 限 が timeout 引 き 数 の 指 す timespec 構 造 体 で 指 定 さ れ た 時 間 と な る 点 だ け が 異 な る (こ の 停 止 期 間 は シ ス テ ム ク ロ ッ ク の 粒 度 に 切 り 上 げ ら れ 、 カ ー ネ ル の ス ケ ジ ュ ー リ ン グ 遅 延 に よ り 、 こ の 停 止 期 間 は 少 し だ け 長 く な る 可 能 性 が あ る )。 指 定 し た 制 限 時 間 に 達 し た 場 合 は 、 semtimedop() は 失 敗 し 、 errnoEAGAIN が 設 定 さ れ る (こ の と き sops の 操 作 は 実 行 さ れ な い )。 timeout 引 き 数 が NULL の 場 合 、 semtimedop() 関 数 の 振 る 舞 い は semop() 関 数 と 全 く 同 じ に な る 。

semtimeop() が シ グ ナ ル に よ り 割 り 込 ま れ た 場 合 、 呼 び 出 し は エ ラ ー EINTR で 失 敗 し 、 timeout の 内 容 は 変 更 さ れ な い ま ま と な る 点 に 注 意 す る こ と 。

返 り 値

成 功 し た 場 合 、 semop() と semtimedop() は 0 を 返 す 。 そ う で な け れ ば −1 を 返 し 、 エ ラ ー を 示 す errno を 設 定 す る 。

エ ラ ー

失 敗 し た 場 合 、 errno に 以 下 の ど れ か が 設 定 さ れ る :

E2BIG

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

EACCES

呼 び 出 し 元 プ ロ セ ス に は 指 定 さ れ た セ マ フ ォ 操 作 を 行 う の に 必 要 な ア ク セ ス 許 可 が な く 、 CAP_IPC_OWNER ケ ー パ ビ リ テ ィ も な い 。

EAGAIN 操 作 を 直 ち に 処 理 す る

こ と が で き ず 、 か つ sem_flgIPC_NOWAIT が 指 定 さ れ て い る か timeout で 指 定 さ れ た 制 限 時 間 が 経 過 し た 。

EFAULT

引 き 数 sopstimeout が 指 し て い る ア ド レ ス に ア ク セ ス で き な い 。

EFBIG あ る 操 作

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

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

EINTR こ の シ ス テ ム コ ー ル で 停 止 し て い る 時 に ス レ ッ ド が シ グ ナ ル を 捕 獲 し た 。

single(7) 参 照 。

EINVAL セ マ フ ォ 集 合 が 存 在 し な い か 、

semid が 0 未 満 で あ る か 、 nsops

正 の 数 で な い 。

ENOMEM あ る 操 作 で

sem_flgSEM_UNDO が 指 定 さ れ た が 、 シ ス テ ム に ア ン

ド ゥ 構 造 体 に 割 り 当 て る 十 分 な メ モ リ ー が な い 。

ERANGE あ る 操 作 で

sem_op+semvalSEMVMX よ り 大 き い 。 SEMVMXsemval

の 最 大 値 で 、 そ の 値 は 実 装 依 存 で あ る 。

バ ー ジ ョ ン

semtimedop() は Linux 2.5.52 で 初 め て 登 場 し 、 そ れ か ら カ ー ネ ル 2.4.22 に も 移 植 さ れ た 。 semtimedop() の glibc で の サ ポ ー ト は バ ー ジ ョ ン 2.3.3 で 初 め て 登 場 し た 。

準 拠

SVr4, POSIX.1−2001.

注 意

Linux や POSIX の 全 て の バ ー ジ ョ ン で は 、 <sys/types.h><sys/ipc.h> の イ ン ク ル ー ド は 必 要 な い 。 し か し な が ら 、 い く つ か の 古 い 実 装 で は こ れ ら の ヘ ッ ダ ー フ ァ イ ル の イ ン ク ル ー ド が 必 要 で あ り 、 SVID で も こ れ ら の イ ン ク ル ー ド を す る よ う に 記 載 さ れ て い る 。 こ の よ う な 古 い シ ス テ ム へ の 移 植 性 を 意 図 し た ア プ リ ケ ー シ ョ ン で は こ れ ら の フ ァ イ ル を イ ン ク ル ー ド す る 必 要 が あ る か も し れ な い 。 あ る プ ロ セ ス の sem_undo 構 造 体 は fork(2) で 生 成 さ れ た 子 プ ロ セ ス に は 継 承 さ れ な い が 、 execve(2) シ ス テ ム コ ー ル の 場 合 は 継 承 さ れ る 。

semop() は シ グ ナ ル ハ ン ド ラ ー に よ っ て 中 断 さ れ た 後 に 、 決 し て 自 動 的 に 再 開 す る こ と は な い 。 た と え シ グ ナ ル ハ ン ド ラ ー の 設 定 時 に SA_RESTART フ ラ グ が セ ッ ト さ れ て い て も 再 開 す る こ と は な い セ マ フ ォ の 調 整 値 (semadj) は 、 プ ロ セ ス 毎 の セ マ フ ォ 毎 の 整 数 で 、 SEM_UNDO フ ラ グ を 指 定 し て 行 わ れ た 、 セ マ フ ォ に 対 す る す べ て の 操 作 の 合 計 値 を 反 転 し た も の で あ る 。 各 プ ロ セ ス は semadj の 値 の リ ス ト を 保 持 す る — リ ス ト の そ れ ぞ れ の 値 は SEM_UNDO を 使 っ て 操 作 が 行 わ れ た 個 々 の セ マ フ ォ に 対 応 す る 。 プ ロ セ ス が 終 了 す る 際 、 セ マ フ ォ 毎 の semadj の 各 々 の 値 が 対 応 す る セ マ フ ォ に 加 算 さ れ る 。 こ れ に よ り 、 そ の プ ロ セ ス が そ の セ マ フ ォ に 対 し て 行 っ た 操 作 の 影 響 が 取 り 消 さ れ る (た だ し 、 下 記 の 「 バ グ 」 を 参 照 )。 semctl(2)SETVALSETALL を 使 っ て セ マ フ ォ の 値 が 直 接 設 定 さ れ た 場 合 、 す べ て の プ ロ セ ス の 対 応 す る semadj の 値 が ク リ ア さ れ る 。 clone(2)CLONE_SYSVSEM フ ラ グ を 使 う と 、 複 数 の プ ロ セ ス が ひ と つ の semadj リ ス ト を 共 有 で き る 。 詳 細 は clone(2) を 参 照 。 あ る セ マ フ ォ の semval, sempid, semzcnt, semnct の 値 は い ず れ も 、 適 切 な 操 作 を 指 定 し て semctl(2) を 呼 び 出 す こ と で 取 得 で き る 。 セ マ フ ォ の 上 限 セ マ フ ォ 集 合 の リ ソ ー ス に 関 す る 制 限 の う ち 、 semop() に 影 響 を 及 ぼ す も の を 以 下 に 挙 げ る :

SEMOPM 一 回 の

semop() で 許 さ れ る 操 作 の 最 大 数 (32)。 (Linux で は 、 こ の

制 限 値 は /proc/sys/kernel/sem の 第 3フ ィ ー ル ド に 対 応 し 、 読 み 出 し も 変 更 も で き る )。

SEMVMX

semval が 取 り 得 る 最 大 値 : 実 装 依 存 (32767)。

以 下 の 値 に 関 し て は 実 装 依 存 の 制 限 は な い 。 終 了 時 の 調 整 (adjust on exit) の 最 大 値 (SEMAEM)、 シ ス テ ム 全 体 の ア ン ド ゥ 構 造 体 の 最 大 数 (SEMMNU)、 プ ロ セ ス あ た り の ア ン ド ゥ 構 造 体 の 最 大 数 。

バ グ

プ ロ セ ス が 終 了 す る 際 、 プ ロ セ ス に 対 応 す る semadj の 集 合 を 使 っ て 、 SEM_UNDO フ ラ グ 付 き で 実 行 さ れ た 全 て の セ マ フ ォ 操 作 の 影 響 を 取 り 消 す 。 こ れ に よ り あ る 問 題 が 発 生 す る : こ れ ら の セ マ フ ォ の 調 整 を 行 っ て い る と 、 中 に は セ マ フ ォ の 値 が 0 未 満 の 値 に し よ う と す る 場 合 が 出 て く る 。 こ の よ う な 場 合 、 ど の よ う に 実 装 す る べ き か ? ひ と つ の 考 え ら れ る 手 法 は 、 全 て の セ マ フ ォ 調 整 が 実 行 さ れ る ま で 停 止 す る こ と で あ る 。 し か し 、 こ の 方 法 で は プ ロ セ ス の 終 了 が 長 時 間 に わ た っ て 停 止 さ れ る こ と が あ る の で 望 ま し く な い 。 し か も ど れ く ら い 長 時 間 に な る か は 分 か ら な い 。 別 の 選 択 肢 と し て 、 こ の よ う な セ マ フ ォ 調 整 を 完 全 に 無 視 し て し ま う 方 法 が あ る (こ れ は セ マ フ ォ 操 作 と し て IPC_NOWAIT が 指 定 す る の と 少 し 似 て い る )。 Linux は 第 三 の 手 法 を 採 用 し て い る : セ マ フ ォ の 値 を 出 来 る だ け (つ ま り 0 ま で ) 減 少 さ せ て 、 プ ロ セ ス の 終 了 を 直 ち に 続 行 で き る よ う に し て い る 。 カ ー ネ ル 2.6.x (x <= 10) に は 、 あ る 状 況 に お い て セ マ フ ォ 値 が 0 に な る の を 待 っ て い る ス レ ッ ド が 、 セ マ フ ォ 値 が 実 際 に 0 に な っ た と き に 起 床 (wake up) さ れ な い 、 と い う バ グ が あ る 。 こ の バ グ は カ ー ネ ル 2.6.11 で 修 正 さ れ て い る 。

以 下 の 部 分 的 な コ ー ド は 、 セ マ フ ォ 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); }

関 連 項 目

clone(2), semctl(2), semget(2), sigaction(2), capabilities(7), sem_overview(7), svipc(7), time(7)

こ の 文 書 に つ い て

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