Как достигается микросекундное время получения linux gettimeofday() и какова его точность?

Время настенных часов обычно предоставляется системами RTC. Это в основном обеспечивает время до миллисекундного диапазона и обычно имеет зернистость 10-20 миллисекунд. Однако разрешение/гранулярность gettimeofday() часто сообщено, чтобы быть в несколько микросекунд. Я предполагаю, что микросекундная гранулярность должна быть взята из другого источника.

Как достигается микросекундное разрешение/гранулярность gettimeofday()?

Когда часть вниз до миллисекунды берется из RTC, а микросекунды берутся с другого оборудования, возникает проблема с фазированием двух источников. Эти два источника должны быть synchronized каким-то образом.

Как выполняется синхронизация/фазировка между этими двумя источниками?

Изменить: Из того, что я прочитал в ссылках, предоставленных amdn, в частности, Intel link, я бы добавил здесь вопрос:

Предоставляет ли gettimeofday() разрешение/гранулярность в микросекундном режиме?


Редактирование 2: подведение итогов amdns с еще несколькими результатами чтения:

Linux использует только часы реального времени (RTC) во время загрузки для синхронизации с счетчиком с более высоким разрешением, т.е. Timestampcounter (TSC). После загрузки gettimeofday() возвращает время, полностью основанное на значении TSC и частоте этого счетчика. Начальное значение для TSC frequency корректируется/откалибровано путем сравнения системного времени с внешним источником времени. Настройка выполняется/настраивается с помощью функции adjtimex(). Ядро работает с фазовой синхронизацией, чтобы гарантировать, что результаты времени являются монотонными и согласованными.

Таким образом, можно сказать, что gettimeofday() имеет разрешение в микросекундах. Принимая во внимание, что более современный Timestampcounter работает в режиме ГГц, получаемая резолюция может быть в наносекундном режиме. Поэтому этот значащий комментарий

/**
407  * do_gettimeofday - Returns the time of day in a timeval
408  * @tv:         pointer to the timeval to be set
409  *
410  * NOTE: Users should be converted to using getnstimeofday()
411  */

можно найти в Linux/kernel/time/timekeeping.c. Это говорит о том, что возможно быть более высокой функцией разрешения, доступной в более поздний момент времени. Прямо сейчас getnstimeofday() доступно только в пространстве ядра.

Однако, просматривая весь код, связанный с этим, чтобы получить это право, вы увидите немало комментариев об неопределенности. Возможно получение микросекундного разрешения. Функция gettimeofday() может даже показать зернистость в микросекундном режиме. Но: Есть серьезные опечатки относительно его точности, потому что точность drift частоты TSC не может быть точно скорректирована. Также сложность кода, связанного с этим вопросом в Linux, - это намек на то, что на самом деле это слишком сложно понять. Это особенно важно, но не только вызвано огромным количеством аппаратных платформ, на которых предполагается запустить Linux.

Результат: gettimeofday() возвращает монотонное время с микросекундной зернистостью, но время, которое он обеспечивает, почти никогда не является фазой one microsecond с любым другим источником времени.

Ответ 1

Как достигается микросекундное разрешение/гранулярность gettimeofday()?

Linux работает на многих различных аппаратных платформах, поэтому особенности различаются. На современной платформе x86 Linux использует Time Stamp Counter, также известный как TSC, который управляется кратным генератором кварцевого генератора на 133,33 МГц. Кристаллический осциллятор обеспечивает опорный тактовый сигнал для процессора, а процессор умножает его на несколько кратных - например, на процессоре с частотой 2,93 ГГц, это число равно 22. История TSC исторически была ненадежным источником времени, поскольку реализации останавливали счетчик, когда процессор перешел в спящий режим или потому, что кратное не было постоянным, так как процессор смещал множители, чтобы изменить состояния производительности или дросселировать, когда он стал горячим, Современные процессоры x86 обеспечивают TSC, который является постоянным, инвариантным и непрерывным. На этих процессорах TSC является отличным высоким разрешением, а ядро ​​Linux определяет начальную приблизительную частоту во время загрузки. TSC обеспечивает микросекундное разрешение для системного вызова gettimeofday() и разрешения наносекунд для системного вызова clock_gettime().

Как выполняется эта синхронизация?

Ваш первый вопрос касался того, как часы Linux обеспечивают высокое разрешение, этот второй вопрос касается синхронизации, это различие между точностью и точностью. В большинстве систем есть часы, которые поддерживаются батареей, чтобы поддерживать время суток, когда система выключена. Как и следовало ожидать, эти часы не имеют высокой точности или точности, но при запуске системы он получит время суток "на стадионе". Чтобы получить точность, большинство систем используют дополнительный компонент для получения времени от внешнего источника в сети. Два общих:

Эти протоколы определяют мастер-часы в сети (или уровень часов, полученных атомными часами), а затем измеряют сетевые задержки для оценки смещений от основного тактового сигнала. Как только смещение от ведущего определяется, системные часы disciplined сохраняют точность. Это можно сделать с помощью

  • Выполнение часов (относительно большая, резкая и нечастая настройка времени) или
  • Slewing часы (определяемые как частота тактовой частоты должна быть скорректирована путем медленного увеличения или уменьшения частоты в течение заданного периода времени)

Ядро предоставляет системный вызов adjtimex, чтобы разрешить часовую дисциплину. Подробнее о том, как современные многоядерные процессоры Intel поддерживают синхронизацию TSC между ядрами, см. Работа с ЦП TSC, особенно в многоядерной многопроцессорной среде.

Соответствующие исходные файлы ядра для регулировки часов kernel/time.c и kernel/time/timekeeping.c.