Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all bug

名前

       nanosleep - 高精度なスリープ

書式

       #include <time.h>

       int nanosleep(const struct timespec *req, struct timespec *rem);

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

       nanosleep(): _POSIX_C_SOURCE >= 199309L

説明

       nanosleep()    は、少なくとも   *req  で指定された時間の間、プログラムの実行を遅延させる。
       nanosleep() は、呼び出したスレッドの実行を、 少なくとも *req  で指定された時間の間、もしく
       は呼び出したスレッドでハンドラーの起動の  きっかけとなるシグナル、またはプロセスを終了させ
       るシグナルの配送が 行われるまで一時停止する。

       呼び出しがシグナルハンドラーにより割り込まれた場合、 nanosleep は  -1  を返し、  errnoEINTR  を設定し、 rem が NULL でなければ 残りの時間を rem が指す構造体に格納する。 *rem の
       値を使うと、 nanosleep()  をもう一度呼び出して、指定した時間の停止を  完了させることができ
       る (但し、「注意」の節を参照のこと)。

       ナノ秒刻みの時間間隔を指定するのに timespec 構造体が使用される。この構造体は次のように定義
       されている。

           struct timespec {
               time_t tv_sec;        /* 秒 */
               long   tv_nsec;       /* ナノ秒 */
           };

       ナノ秒のフィールドの値は 0 から 999999999 の範囲になければならない。

       sleep(3)  や usleep(3)  に比べると nanosleep()  には以下のような利点がある: 停止期間の指定
       に関して高い時間分解能が提供されている。  シグナルと互いに影響を及ぼすことがないと POSIX.1
       で明示的に規定されている。  シグナルハンドラーによって割り込まれた際に、停止を再開するのが
       より簡単にできる。

返り値

       要求された期間の停止に成功した場合、  nanosleep()   は  0 を返す。呼び出しがシグナルハンド
       ラーにより割り込まれたり、 エラーが発生した場合は、-1 を返し、 errno  にエラー内容を示す値
       を設定する。

エラー

       EFAULT ユーザー空間からの情報のコピーで問題があった。

       EINTR  そのスレッドに配送されたシグナルにより停止が中断された  (signal(7) 参照)。 スレッド
              が簡単に nanosleep() を再び呼び出して停止を続けることができるように、  残りの停止時
              間が *rem に格納される。

       EINVAL tv_nsec  フィールドの値が  0  から 999999999 の範囲でないか、 tv_sec の値が負であっ
              た。

準拠

        POSIX.1-2001, POSIX.1-2008.

注意

       req で指定された期間が、内部で使用されるクロックの粒度の倍数になっていない  場合、期間は一
       番近い倍数に切り上げられる。  また、停止が完了した後、CPU が呼び出し元のスレッドを再び実行
       できるように なるまでには遅延が入る。

       シグナルによる割り込み後に繰り返し再開された場合、 nanosleep()  の停止が相対的な期間である
       ことは問題となることがある。 これは、呼び出しの割り込みから再開までの間の時間が原因で 停止
       が最終的に完了した際に時間にずれが発生するからである。    この問題は、絶対時刻が指定できる
       clock_nanosleep(2)  を使うことで回避できる。

       POSIX.1  は、  nanosleep()  は CLOCK_REALTIME に対して時刻を計測するべきだと規定している。
       しかしながら、Linux は CLOCK_MONOTONIC クロックを用いて時刻を計測している。 このことはおそ
       らく問題にならないだろう。    なぜなら、POSIX.1    の    clock_settime(2)     の仕様には、
       CLOCK_REALTIME の不連続な変化は nanosleep()   に影響すべきではない、と書かれているからであ
       る。

              clock_settime(2)  経由で CLOCK_REALTIME クロックの値を設定しても、 nanosleep() 関数
              などの CLOCK_REALTIME  に基づくサービスにより相対的な期間だけ実行を停止するスレッド
              には影響はない。 結果として、クロック値が更新前か後かに関わらず、要求された相対的な
              時間が 経過すると満了することになる。

   以前の動作
       In order to support applications requiring much more precise pauses  (e.g.,  in  order  to
       control  some  time-critical  hardware),  nanosleep()   would  handle  pauses  of  up to 2
       milliseconds by busy  waiting  with  microsecond  precision  when  called  from  a  thread
       scheduled  under  a  real-time policy like SCHED_FIFO or SCHED_RR.  This special extension
       was removed in kernel 2.5.39, and is thus not available in Linux 2.6.0 and later kernels.

バグ

       If a program that catches signals and uses nanosleep()  receives signals at  a  very  high
       rate,  then scheduling delays and rounding errors in the kernel's calculation of the sleep
       interval and the returned remain value mean that the remain value may steadily increase on
       successive   restarts   of   the   nanosleep()    call.    To  avoid  such  problems,  use
       clock_nanosleep(2)  with the TIMER_ABSTIME flag to sleep to an absolute deadline.

       In Linux 2.4, if nanosleep()  is stopped by a signal (e.g., SIGTSTP), then the call  fails
       with  the error EINTR after the thread is resumed by a SIGCONT signal.  If the system call
       is subsequently restarted, then the time that the thread spent in the stopped state is not
       counted  against  the  sleep  interval.   This  problem  is fixed in Linux 2.6.0 and later
       kernels.

関連項目

       clock_nanosleep(2), restart_syscall(2), sched_setscheduler(2), timer_create(2),  sleep(3),
       usleep(3), time(7)

この文書について

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