NANOSLEEP(2)

名前
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 を返し、 errno に EINTR を設定し、 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/ に書かれている。