OSDN Git Service

c3d785bd9cbe9c417193a3ca3ce00eecb5a6315c
[linuxjm/LDP_man-pages.git] / release / man3 / sem_wait.3
1 '\" t
2 .\" Hey Emacs! This file is -*- nroff -*- source.
3 .\"
4 .\" Copyright (C) 2006 Michael Kerrisk <mtk.manpages@gmail.com>
5 .\"
6 .\" Permission is granted to make and distribute verbatim copies of this
7 .\" manual provided the copyright notice and this permission notice are
8 .\" preserved on all copies.
9 .\"
10 .\" Permission is granted to copy and distribute modified versions of this
11 .\" manual under the conditions for verbatim copying, provided that the
12 .\" entire resulting derived work is distributed under the terms of a
13 .\" permission notice identical to this one.
14 .\"
15 .\" Since the Linux kernel and libraries are constantly changing, this
16 .\" manual page may be incorrect or out-of-date.  The author(s) assume no
17 .\" responsibility for errors or omissions, or for damages resulting from
18 .\" the use of the information contained herein.  The author(s) may not
19 .\" have taken the same level of care in the production of this manual,
20 .\" which is licensed free of charge, as they might when working
21 .\" professionally.
22 .\"
23 .\" Formatted or processed versions of this manual, if unaccompanied by
24 .\" the source, must acknowledge the copyright and authors of this work.
25 .\"
26 .\" Japanese Version Copyright (c) 2006 Akihiro MOTOKI all rights reserved.
27 .\" Translated 2006-04-18, Akihiro MOTOKI <amotoki@dd.iij4u.or.jp>
28 .\"
29 .TH SEM_WAIT 3 2010-02-25 "Linux" "Linux Programmer's Manual"
30 .SH 名前
31 sem_wait, sem_timedwait, sem_trywait \- セマフォをロックする
32 .SH 書式
33 .nf
34 .B #include <semaphore.h>
35 .sp
36 .BI "int sem_wait(sem_t *" sem );
37 .sp
38 .BI "int sem_trywait(sem_t *" sem );
39 .sp
40 .BI "int sem_timedwait(sem_t *" sem ", const struct timespec *" abs_timeout );
41 .fi
42 .sp
43 .sp
44 \fI\-lrt\fP または \fI\-pthread\fP でリンクする。
45 .in -4n
46 glibc 向けの機能検査マクロの要件
47 .RB ( feature_test_macros (7)
48 参照):
49 .in
50 .sp
51 .BR sem_timedwait ():
52 _POSIX_C_SOURCE\ >=\ 200112L || _XOPEN_SOURCE\ >=\ 600
53 .SH 説明
54 .BR sem_wait ()
55
56 .I sem
57 が指すセマフォの値を 1 減らす (ロックする)。
58 セマフォの値が 0 より大きい場合、減算が実行され、関数は直ちに復帰する。
59 セマフォの現在値が 0 の場合には、減算を実行できるようになる
60 (つまり、セマフォの値が 0 より大きな値になる) まで、もしくは
61 シグナルハンドラによって呼び出しが中断されるまで、
62 関数呼び出しは停止 (block) する。
63
64 .BR sem_trywait ()
65
66 .BR sem_wait ()
67 と同じだが、セマフォ値の減算をすぐに実行できなかった場合に、
68 停止 (block) するのではなくエラーで復帰する
69 .RI ( errno
70
71 .B EAGAIN
72 がセットされる) 点が異なる。
73
74 .BR sem_timedwait ()
75
76 .BR sem_wait ()
77 と同じだが、セマフォ値の減算をすぐに実行できなかった場合に
78 関数呼び出しが停止する時間の上限を
79 .I abs_timeout
80 で指定する点が異なる。
81 .I abs_timeout
82 引き数は、タイムアウト時刻を指定する構造体へのポインタである。
83 この構造体には、タイムアウト時刻を時刻紀元 (Epoch;
84 1970-01-01 00:00:00 +0000 (UTC)) からの
85 経過時間 (秒+ナノ秒) で指定する。
86 構造体は以下のように定義されている:
87
88 .nf
89 .in +4n
90 struct timespec {
91     time_t tv_sec;      /* Seconds */
92     long   tv_nsec;     /* Nanoseconds [0 .. 999999999] */
93 };
94 .in
95 .fi
96 .PP
97 関数呼び出し時点ですでにタイムアウトに指定した時刻が過ぎており、
98 かつセマフォをすぐにロックできなかった場合は、
99 .BR sem_timedwait ()
100 はタイムアウトエラー
101 .RI ( errno
102
103 .B ETIMEDOUT
104 がセットされる) で失敗する。
105
106 セマフォ操作がすぐに実行できるときは、
107 .I abs_timeout
108 がどんな値であっても
109 .BR sem_timedwait ()
110 が失敗することは決してない。さらにいうと、この場合には
111 .I abs_timeout
112 の正当性の検査は行われない。
113 .SH 返り値
114 成功すると、これらの関数は 0 を返す。
115 エラーの場合、セマフォの値を変更せずに、\-1 を返し、
116 .I errno
117 にエラーを示す値をセットする。
118 .SH エラー
119 .TP
120 .B EINTR
121 呼び出しはシグナルハンドラにより中断された。
122 .BR signal (7)
123 参照。
124 .TP
125 .B EINVAL
126 .I sem
127 は有効なセマフォでない。
128 .PP
129 .BR sem_trywait ()
130 の場合には、上記に加えて以下のエラーも起こる。
131 .TP
132 .B EAGAIN
133 停止 (block) せずにロック操作を完了できなかった (つまり、
134 セマフォの現在の値が 0 であった)。
135 .PP
136 .BR sem_timedwait ()
137 の場合、以下のエラーも起こる。
138 .TP
139 .B EINVAL
140 .I abs_timeout.tv_nsecs
141 の値が 0 未満、もしくは 1,000,000,000 以上である。
142 .TP
143 .B ETIMEDOUT
144 セマフォのロックに成功する前に時間切れとなった。
145 .\" POSIX.1-2001 ではエラーとして EDEADLK も用意している。
146 .\" これはデッドロック条件を検出したことを示すものだが、
147 .\" Linux で発生することはない(?)
148 POSIX.1-2001.
149 .SH 注意
150 シグナルハンドラは、
151 .BR sigaction (2)
152
153 .B SA_RESTART
154 フラグを使用しているかどうかに関わらず、これらの関数の呼び出しが
155 停止している場合、シグナルハンドラにより常に中断される。
156 .\" sem_wait() は他のほとんどの実装では常に中断されるが、
157 .\" FreeBSD 5.4 では SA_RESTART を指定しておくと実行が再開される。
158 .SH 例
159 .PP
160 以下に示す (ちょっとした) プログラムは名前なしセマフォの操作を行う。
161 プログラムはコマンドライン引き数を 2 つ取る。
162 最初の引き数には、
163 .B SIGALRM
164 シグナルを生成するためのアラームタイマーの設定に使われる値を
165 秒単位で指定する。このシグナルハンドラは、
166 .I main()
167 内で
168 .BR sem_timedwait ()
169 を使って待っているセマフォを、
170 .BR sem_post (3)
171 を使って加算する。
172 2番目の引き数には、
173 .BR sem_timedwait ()
174 に渡すタイムアウトまでの時間を秒単位で指定する。
175
176 .in +4n
177 .nf
178 .RB "$" " ./a.out 2 3"
179 About to call sem_timedwait()
180 sem_post() from handler
181 sem_getvalue() from handler; value = 1
182 sem_timedwait() succeeded
183 .RB "$" " ./a.out 2 1"
184 About to call sem_timedwait()
185 sem_timedwait() timed out
186 .fi
187 .in
188 .SS プログラムのソース
189 \&
190 .nf
191 #include <unistd.h>
192 #include <stdio.h>
193 #include <stdlib.h>
194 #include <semaphore.h>
195 #include <time.h>
196 #include <assert.h>
197 #include <errno.h>
198 #include <signal.h>
199
200 sem_t sem;
201
202 #define handle_error(msg) \\
203     do { perror(msg); exit(EXIT_FAILURE); } while (0)
204
205 static void
206 handler(int sig)
207 {
208     write(STDOUT_FILENO, "sem_post() from handler\\n", 24);
209     if (sem_post(&sem) == \-1) {
210         write(STDERR_FILENO, "sem_post() failed\\n", 18);
211         _exit(EXIT_FAILURE);
212     }
213 }
214
215 int
216 main(int argc, char *argv[])
217 {
218     struct sigaction sa;
219     struct timespec ts;
220     int s;
221
222     if (argc != 3) {
223         fprintf(stderr, "Usage: %s <alarm\-secs> <wait\-secs>\\n",
224                 argv[0]);
225         exit(EXIT_FAILURE);
226     }
227
228     if (sem_init(&sem, 0, 0) == \-1)
229         handle_error("sem_init");
230
231     /* Establish SIGALRM handler; set alarm timer using argv[1] */
232
233     sa.sa_handler = handler;
234     sigemptyset(&sa.sa_mask);
235     sa.sa_flags = 0;
236     if (sigaction(SIGALRM, &sa, NULL) == \-1)
237         handle_error("sigaction");
238
239     alarm(atoi(argv[1]));
240
241     /* Calculate relative interval as current time plus
242        number of seconds given argv[2] */
243
244     if (clock_gettime(CLOCK_REALTIME, &ts) == \-1)
245         handle_error("clock_gettime");
246
247     ts.tv_sec += atoi(argv[2]);
248
249     printf("main() about to call sem_timedwait()\\n");
250     while ((s = sem_timedwait(&sem, &ts)) == \-1 && errno == EINTR)
251         continue;       /* Restart if interrupted by handler */
252
253     /* Check what happened */
254
255     if (s == \-1) {
256         if (errno == ETIMEDOUT)
257             printf("sem_timedwait() timed out\\n");
258         else
259             perror("sem_timedwait");
260     } else
261         printf("sem_timedwait() succeeded\\n");
262
263     exit((s == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
264 }
265 .fi
266 .SH 関連項目
267 .BR clock_gettime (2),
268 .BR sem_getvalue (3),
269 .BR sem_post (3),
270 .BR sem_overview (7),
271 .BR time (7)