Разница между CLOCK_REALTIME и CLOCK_MONOTONIC?


206

Не могли бы вы объяснить разницу между CLOCK_REALTIMEи CLOCK_MONOTONICЧАСЫ возвращаемые clock_gettime()на Linux?

Какой вариант лучше выбрать, если мне нужно вычислить прошедшее время между временными метками, созданными внешним источником, и текущим временем?

Наконец, если у меня есть демон NTP, периодически меняющий системное время, как эти настройки взаимодействуют с каждым из CLOCK_REALTIMEи CLOCK_MONOTONIC?

Ответы:


238

CLOCK_REALTIMEпредставляет предположение машины о текущих настенных часах, времени суток. Как говорят Игнасио и МаркР , это означает, что они CLOCK_REALTIMEмогут прыгать вперед и назад при изменении системных часов, включая NTP.

CLOCK_MONOTONICпредставляет абсолютное истекшее время настенных часов с некоторой произвольной фиксированной точки в прошлом. На него не влияют изменения системных часов времени.

Если вы хотите вычислить истекшее время между двумя событиями, наблюдаемыми на одной машине, без промежуточной перезагрузки, CLOCK_MONOTONICэто лучший вариант.

Обратите внимание, что в Linux CLOCK_MONOTONICне измеряется время, затраченное на приостановку, хотя по определению POSIX это должно быть. Вы можете использовать специфичные CLOCK_BOOTTIMEдля Linux монотонные часы, которые продолжают работать в режиме ожидания.


11
Обратите внимание, что в более новых ядрах доступен CLOCK_MONOTONIC_RAW, что даже лучше (без настроек NTP).
Джозеф Гарвин

14
@JosephGarvin для некоторого значения «лучше», возможно - CLOCK_MONOTONIC_RAW может работать быстро или медленно в реальном времени на несколько (или несколько сотен) частей на миллион, и его скорость может варьироваться в зависимости от условий окружающей среды, таких как температура или напряжение (или время кражи на виртуальные машины). На правильно-рабочей машине, NTP делает все возможное , чтобы смягчить все эти факторы и поэтому CLOCK_MONOTONIC более точно отражает истинное истекшее время.
Хоббс

23
Конечно, может быть интересно иметь CLOCK_MONOTONIC_PARBOILED, на который влияют усилия NTP по исправлению частотных ошибок, но не затрагиваемые его усилиями по исправлению фазовых ошибок, но это большая сложность для сомнительного усиления :)
Хоббс

1
Мне нравится то, что поднимает @hobbs. Что если вы беспокоитесь о программах, на которые может повлиять сдвиг часов? Будет CLOCK_MONOTONICли лучший выбор в этом сценарии? например, Ракетная система Патриот
sjagr

3
Я думаю, что также важно упомянуть, что CLOCK_REALTIME зависит от дополнительных секунд. Это означает, что он будет выдавать двойные временные метки каждый раз, когда добавляется високосная секунда. В последний раз это произошло 30 июня 2012 года, и многие программы столкнулись с проблемами .
user1202136

38

Книга Роберта Лава, посвященная системному программированию LINUX, 2-е издание , конкретно рассматривает ваш вопрос в начале главы 11, стр. 363:

Важным аспектом монотонного источника времени является НЕ текущее значение, а гарантия того, что источник времени строго линейно увеличивается, и, следовательно, полезен для расчета разницы во времени между двумя выборками.

Тем не менее, я полагаю, что он предполагает, что процессы выполняются в одном и том же экземпляре ОС, поэтому вам может потребоваться периодическая калибровка для оценки дрейфа.


25

CLOCK_REALTIMEНа него влияет NTP, и он может двигаться вперед и назад. CLOCK_MONOTONICнет, и продвигается на один тик за тик.


15
CLOCK_MONOTONIC зависит от настройки времени NTP (время поворота). Это не будет прыгать, однако.
Дероберт

3
Но в более новых ядрах есть CLOCK_MONOTONIC_RAW, который действительно не зависит от NTP.
Джозеф Гарвин

1
"галочка" - какая-то грубая идея о том, насколько большие / длинные / процессорные инструкции являются галочкой в ​​Linux / amd64? Или где я могу получить документы на все это?
Кевинарпе

@kevinarpe Не уверен, но я думаю, что тик определяется как доля времени, а не количество циклов процессора, часто это 1/100 секунды.
Стефан

@ Стефан: Я, конечно, должен быть крепче, чем 10 мс. Я думаю, что Java System.nanoTime()использует CLOCK_MONOTONICи может измерять продолжительность 1000 нс или меньше. Может быть, вы думаете о системном времени, которое иногда ограничивается миллисекундами?
Кевинарпе

20

В дополнение к ответу Игнасио , CLOCK_REALTIMEможет подняться вперед скачком, а иногда и назад. CLOCK_MONOTONICне делает ни; он просто продолжает двигаться вперед (хотя, вероятно, он сбрасывается при перезагрузке).

Надежное приложение должно быть способно выдерживать CLOCK_REALTIMEскачкообразный скачок вперед (и, возможно, очень незначительно назад, иногда, хотя это скорее крайний случай).

Представьте, что происходит, когда вы подвешиваете свой ноутбук - CLOCK_REALTIMEпрыгает вперед, следуя резюме, CLOCK_MONOTONICне делает. Попробуйте это на ВМ.


3
CLOCK_MONOTONIC начинается с 0 при запуске программы; это не для межпроцессного использования.
Benubird

18
@Benubird: не запускается в 0 при запуске программы. Это CLOCK_PROCESS_CPUTIME_ID. Быстрый тест: $ perl -w -MTime::HiRes=clock_gettime,CLOCK_MONOTONIC -E 'say clock_gettime(CLOCK_MONOTONIC)'-> 706724.117565279. Это число соответствует времени работы системы в Linux, но стандарт говорит, что это произвольно.
Дероберт

4
Кроме того, я не верю, что поведение Linux, когда CLOCK_MONOTONICостановка приостанавливается / возобновляется, соответствует POSIX. Предполагается, что это было время с фиксированной точки в прошлом, но остановка часов из-за приостановки / возобновления ломает это.
Кафе

15

POSIX 7 цитаты

POSIX 7 указывает оба на http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html :

CLOCK_REALTIME:

Эти часы представляют часы, измеряющие реальное время для системы. Для этих часов значения, возвращаемые функцией clock_gettime () и определяемые функцией clock_settime (), представляют количество времени (в секундах и наносекундах) с начала эпохи.

CLOCK_MONOTONIC (дополнительная функция):

Для этих часов значение, возвращаемое функцией clock_gettime (), представляет количество времени (в секундах и наносекундах) с неопределенной точки в прошлом (например, время запуска системы или эпоха). Эта точка не меняется после запуска системы. Значение часов CLOCK_MONOTONIC не может быть установлено с помощью clock_settime ().

clock_settime()дает важный совет: системы POSIX могут произвольно меняться CLOCK_REALITMEвместе с ним, поэтому не полагайтесь на то, что он течет ни непрерывно, ни вперед. NTP может быть реализован с использованием clock_settime()и может повлиять только CLOCK_REALITME.

Реализация ядра Linux, по-видимому, требует времени загрузки в качестве эпохи для CLOCK_MONOTONIC: отправной точки для CLOCK_MONOTONIC


0

Извините, нет репутации, чтобы добавить это как комментарий. Так что это идет как дополнительный ответ.

В зависимости от того, как часто вы будете звонить clock_gettime(), вы должны иметь в виду, что Linux предоставляет только некоторые из «часов» в VDSO (то есть не требует системного вызова со всеми дополнительными издержками, что только ухудшается, когда добавляется Linux). защита для защиты от атак, подобных призраку).

В то время clock_gettime(CLOCK_MONOTONIC,...), clock_gettime(CLOCK_REALTIME,...)и gettimeofday()всегда будет очень быстро (ускорен VDSO), это не относится к, например , CLOCK_MONOTONIC_RAW или любой из других POSIX часов.

Это может измениться в зависимости от версии ядра и архитектуры.

Хотя большинству программ не нужно обращать на это внимание, в VDSO могут наблюдаться всплески задержек в часах, ускоряемые VDSO: если вы нажмете их правильно, когда ядро ​​обновляет область общей памяти с помощью счетчиков тактовых импульсов, оно должно ждать ядро закончить.

Вот «доказательство» (GitHub, чтобы держать ботов подальше от kernel.org): https://github.com/torvalds/linux/commit/2aae950b21e4bc789d1fc6668faf67e8748300b7


0

CLOCK_REALTIME : Абсолютное время (например, 07/01/2020)

CLOCK_MONOTONIC: Относительное время (например, 5 секунд или 10 минут назад)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.