CLOCK_GETRES(2) Руководство программиста Linux CLOCK_GETRES(2)

ИМЯ

clock_getres, clock_gettime, clock_settime - функции часов и времени

ОБЗОР

#include <time.h>

int clock_getres(clockid_t clk_id, struct timespec *res);

int clock_gettime(clockid_t clk_id, struct timespec *tp);

int clock_settime(clockid_t clk_id, const struct timespec *tp);

Компонуется при указании параметра -lrt (только для glibc до версии 2.17).

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

clock_getres(), clock_gettime(), clock_settime():

_POSIX_C_SOURCE >= 199309L

ОПИСАНИЕ

Функция clock_getres() определяет разрешающую способность (точность) заданных в clk_id часов, и, если res не равно NULL, сохраняет её в struct timespec, указанную в res. Точность часов зависит от реализации и не может быть настроена определённым процессом. Если значение времени, указанное в аргументе tp функции clock_settime(), не кратно res, то оно усекается до кратного res.

Функции clock_gettime() и clock_settime() получают и устанавливают время указанных часов clk_id.

Аргументы res и tp представляют структуру timespec, определённую в <time.h>:

struct timespec {

    time_t   tv_sec;        /* секунды */

    long     tv_nsec;       /* наносекунды */
};

Аргумент clk_id представляет идентификатор определённых часов, над которыми производится действие. Часы могут использоваться системой в целом и поэтому видимы всем процессам или конкретного процессу, если они отсчитывают время только в пределах одного процесса.

Все реализации поддерживают системные часы реального времени, которые имеют идентификатор CLOCK_REALTIME. Их время представляется в секундах и наносекундах с начала Эпохи. Когда их время изменяется, на таймеры с относительными интервалами это никак не влияет, но таймеры с абсолютной точкой во времени учитывают это.

Может быть реализовано много часов. Представление соответствующих значений времени и влияние на таймеры не определено.

В последних версиях glibc и ядра Linux поддерживаются следующие часы:

Часы системы, отсчитывающие реальное (т. е., бытовое) время. Для настройки этих часов требуются соответствующие права. Данные часы подвержены скачкам системного времени (например, если системный администратор вручную изменяет время) и постепенной подгонке, выполняемой adjtime(3) и NTP.
Более быстрая, но менее точная версия CLOCK_REALTIME. Используйте, если нужны не очень точные метки времени, но очень быстро. Требуется поддержка в архитектуре и, вероятно, поддержка архитектурой этого флага в vdso(7).
Часы, которые не могут быть настроены и показывают монотонный ход времени, отсчитываемый, согласно POSIX, «с некой неопределённой начальной точки в прошлом». В Linux этой точкой является количество секунд, прошедших с момента начала загрузки системы.
Часы CLOCK_MONOTONIC не подвержены скачкам системного времени (например, системный администратор вручную изменил время), но на них влияет постепенная подгонка, выполняемая adjtime(3) и NTP. Данные часы не считают время при приостановке системы.
Более быстрая, но менее точная версия CLOCK_MONOTONIC. Используйте, если нужны не очень точные метки времени, но очень быстро. Требуется поддержка в архитектуре и, вероятно, поддержка архитектурой этого флага в vdso(7).
Похожи на CLOCK_MONOTONIC, но предоставляют прямой доступ к аппаратным часам, которые не подводятся NTP или постепенной подгонкой, выполняемой adjtime(3). Эти часы останавливаются когда система входит в состояние приостановки.
Идентичны CLOCK_MONOTONIC, но также содержат любое время, на которое система была приостановлена (suspended). Это позволяет приложениям получить учитывающие приостановку монотонные часы без обращения к сложностям CLOCK_REALTIME, которые могут быть неоднородны, если время изменили с помощью settimeofday(2) или ему подобных.
Настраиваемые для каждого процесса часы ЦП (измеряют время ЦП, затраченное всеми нитями процесса).
Часы, работающие на ЦП, для каждой нити.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении функции clock_gettime(), clock_settime() и clock_getres() возвращают 0, или -1 в случае ошибки (errno устанавливается в соответствующее значение).

ОШИБКИ

tp указывает за пределы доступного адресного пространства.
Заданное в clk_id значение не поддерживается на этой системе.
(clock_settime()): tp.tv_sec отрицательно или tp.tv_nsec вне диапазона [0..999,999,999].
Вызов clock_settime() со значением clk_id равным CLOCK_REALTIME для установки времени в значение меньше текущего значения часов CLOCK_MONOTONIC.
Для установки указанных часов с помощью clock_settime() недостаточно прав.

ВЕРСИИ

Данные системные вызовы впервые появились в Linux 2.6.

АТРИБУТЫ

Описание терминов данного раздела смотрите в attributes(7).

Интерфейс Атрибут Значение
clock_getres(), clock_gettime(), clock_settime() Безвредность в нитях MT-Safe

СООТВЕТСТВИЕ СТАНДАРТАМ

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

ДОСТУПНОСТЬ

На POSIX-системах, в которых доступны эти функции, символ _POSIX_TIMERS, определённый в <unistd.h>, имеет значение больше 0. Символами _POSIX_MONOTONIC_CLOCK, _POSIX_CPUTIME, _POSIX_THREAD_CPUTIME показывается, что доступны CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID. (см. также sysconf(3).)

ЗАМЕЧАНИЯ

В POSIX.1 определено следующее:

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

Отличия между библиотекой C и ядром

На некоторых архитектурах реализация clock_gettime() находится в vdso(7).

Историческая справка по системам SMP

До того, как в Linux была добавлена поддержка CLOCK_PROCESS_CPUTIME_ID и CLOCK_THREAD_CPUTIME_ID, реализация этих часов в glibc на многих платформах использовала регистры таймеры ЦП (TSC на i386, AR.ITC на Itanium). Эти регистры могут отличаться у разных ЦП и, как следствие, эти часы могут возвращать поддельные результаты, если выполнение процесса переходит на другой ЦП.

Если процессоры в многопроцессорных системах используют разные источники времени, то нет способа поддерживать сверку между регистрами таймера, так как каждый ЦП будет работать со слегка отличающейся частотой. В этом случае clock_getcpuclockid(0) вернёт ENOENT, чтобы указать на это состояние. Двое часов в этом случае будут полезны, только если можно убедиться, что процесс остался на определённом ЦП.

Процессоры в многопроцессорных системах не приступают к работе одновременно и поэтому регистры таймера обычно работают со смещением. Некоторые архитектуры содержат код, который пытается сократить это смещение при загрузке системы. Однако код не может гарантировать точную подстройку смещений. В glibc нет средств для работы с этими смещениями (в отличие от ядра Linux). Обычно, эти смещения малы и поэтому, в большинстве случаев, их влияние незначительно.

Начиная с glibc 2.4, обёрточные функции системных вызовов, описанных на этой странице, не имеют таких проблем, так как используют ядерную реализацию CLOCK_PROCESS_CPUTIME_ID и CLOCK_THREAD_CPUTIME_ID (в системах, которые её предоставляют, то есть Linux 2.6.12 и новее).

ДЕФЕКТЫ

Согласно POSIX.1-2001, процесс с «соответствующими правами» может настроить часы CLOCK_PROCESS_CPUTIME_ID и CLOCK_THREAD_CPUTIME_ID с помощью clock_settime(). В Linux эти часы не допускают настройку (т. е., процесс не может иметь «соответствующие права»).

СМОТРИТЕ ТАКЖЕ

date(1), gettimeofday(2), settimeofday(2), time(2), adjtime(3), clock_getcpuclockid(3), ctime(3), ftime(3), pthread_getcpuclockid(3), sysconf(3), time(7), vdso(7), hwclock(8)

2019-03-06