nanosleep(2)

ИМЯ
nanosleep - остановка работы процесса с более точным указанием периода

LIBRARY
Standard C library (libc, -lc)

СИНТАКСИС
#include <time.h>

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

    Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

nanosleep():
    _POSIX_C_SOURCE >= 199309L

ОПИСАНИЕ
nanosleep() приостанавливает работу вызывающей нити как минимум на время, заданное параметром *req, или до получения сигнала, который вызовет обработчик в вызывающей нити, или приведёт к завершению процесса.

Если вызов прерван обработчиком сигнала, то nanosleep() возвращает -1, устанавливает errno в значение EINTR и записывает оставшееся время в структуру, на которую указывает rem, если значение rem не равно NULL. Значение *rem можно использовать для повторения вызова nanosleep() и продления окончания ожидания интервала (но см. ЗАМЕЧАНИЯ).

The timespec(3) structure is used to specify intervals of time with nanosecond precision.

The value of the nanoseconds field must be in the range [0, 999999999].

По сравнению с sleep(3) и usleep(3), в nanosleep() есть следующие достоинства: он позволяет задавать более точные интервалы времени, в POSIX.1 явно определено то, что он не влияет на сигналы, и позволяет более лёгким способом возобновить паузу после прерывания сигналом.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При удачной остановке на заданное время возвращаемое nanosleep() значение равно нулю. Если вызов прерван обработчиком сигнала или произошла ошибка, то возвращается -1, а переменной errno присваивается номер ошибки.

ОШИБКИ

EFAULT
    Проблема с копированием информации из пространства пользователя.

EINTR
    Пауза была прервана сигналом, отправленным нити (смотрите signal(7)). Оставшееся время записано в *rem для того, чтобы нить могла вызвать nanosleep() снова для возобновления паузы.

EINVAL
    The value in the tv_nsec field was not in the range [0, 999999999] or tv_sec was negative.

СТАНДАРТЫ
POSIX.1-2001, POSIX.1-2008.

ЗАМЕЧАНИЯ
Если интервал, указанный в req, не кратен степени разрешения используемых часов (см. time(7)), то интервал будет округлён до следующего кратного значения. Также, после окончания интервала приостановки может возникнуть задержка перед тем, как ЦП освободится снова для следующего выполнения вызывающей нити.

Тот факт, что nanosleep() вызывает приостановку на относительный интервал, может привести к проблемам, если вызов постоянно перезапускается после прерывания по сигналу, так как время между прерываниями и перезапуском вызова будет приводить к временному смещению полного завершения приостановки. Этой проблемы можно избежать, если использовать clock_nanosleep(2) с абсолютными величинами времени.

В POSIX.1 указано, что nanosleep() должен измерять время по часам CLOCK_REALTIME. Однако, в Linux время измеряется с помощью часов CLOCK_MONOTONIC. Это, скорее всего, не важно, так как в спецификации POSIX.1 для clock_settime(2) указано, что быстро происходящие изменения в CLOCK_REALTIME не должны влиять на nanosleep():

    Установка значения часов CLOCK_REALTIME с помощью clock_settime(2) не оказывает влияния на нити, которые находятся в состоянии простоя из-за служб, работа которых основана на этих часах, включая функцию nanosleep(); ... В результате, интервал данных служб истечёт, когда истечёт запрошенный относительный интервал, независимо от нового или старого значения часов.

  Старое поведение
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 Linux 2.5.39, and is thus not available in Linux 2.6.0 and later kernels.

ДЕФЕКТЫ
Если программа, обрабатывающая сигналы и использующая nanosleep(), принимает сигналы с очень высокой частотой, то возникают задержки планирования и ошибки округления в ядерных подсчётах интервала сна и возвращается значение остатка, на которое можно уверенно увеличивать интервал при последующем перезапуске вызова nanosleep(). Чтобы избежать таких проблем используйте clock_nanosleep(2) с флагом TIMER_ABSTIME, чтобы спать до абсолютного конечного срока.

В Linux 2.4, если nanosleep() останавливается по сигналу (например, SIGTSTP), то после того, как нить продолжит работу по сигналу SIGCONT, вызов завершится неудачно с ошибкой EINTR. Если системный вызов после этого перезапускается, то время, которое нить провела в остановленном состоянии, не учитывается в интервале остановки. Эта проблема исправлена в Linux 2.6.0 и новее.

СМ. ТАКЖЕ
clock_nanosleep(2), restart_syscall(2), sched_setscheduler(2), timer_create(2), sleep(3), timespec(3), usleep(3), time(7)

ПЕРЕВОД
Русский перевод этой страницы руководства был сделан Alex Nik <rage.iz.me@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 (https://www.gnu.org/licenses/gpl-3.0.html) или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.