Выбрать главу

Системный вызов settimeofday() является обратным функции gettimeofday() (рассмотренной в разделе 10.1): он присваивает календарному времени системы значение, соответствующее количеству секунд и микросекунд, заданное в структуре timeval, указатель на которую находится в аргументе tv.

#define _BSD_SOURCE

#include <sys/time.h>

int settimeofday(const struct timeval *tv, const struct timezone *tz);

Возвращает при успешном завершении 0 или –1 при ошибке

Как и в случае с gettimeofday(), использование аргумента tz утратило актуальность, и в качестве его значения нужно указывать NULL.

Точность до микросекунд в поле v.tv_usec не означает наличие такой же точности в управлении системными часами, поскольку точность у часов может быть ниже одной микросекунды.

Хотя системный вызов settimeofday() в SUSv3 не определен, он широко доступен во многих других реализациях UNIX.

В Linux также предоставляется системный вызов stime(), предназначенный для установки системных часов. Разница между settimeofday() и stime() состоит в том, что последний вызов позволяет установить новое календарное время с точностью всего лишь в одну секунду. Как и в случае с time() и gettimeofday(), причина существования как stime(), так и settimeofday() имеет исторические корни: последний, задающий более точное значение вызов был добавлен в версии 4.2BSD.

Резкие изменения системного времени, связанные с вызовами settimeofday(), могут плохо влиять на приложения (например, на make(1), систему управления базами данных, использующую метки времени, или на файлы журналов, использующие метки времени). Поэтому при внесении незначительных изменений в установки времени (в пределах нескольких секунд) практически всегда предпочтительнее задействовать библиотечную функцию adjtime(), заставляющую системные часы постепенно выйти на требуемое значение.

#define _BSD_SOURCE

#include <sys/time.h>

int adjtime(struct timeval *delta, struct timeval *olddelta);

Возвращает при успешном завершении 0 или –1 при ошибке

Аргумент delta указывает на структуру timeval, определяющую количество секунд и микросекунд, на которое нужно изменить время. При положительном значении время добавляется к системным часам небольшими порциями каждую секунду до тех пор, пока не будет добавлено требуемое значение. При отрицательном значении delta ход часов замедляется в том же режиме.

Скорость изменения в Linux/x86-32 составляет одну секунду за каждые 2000 секунд (или 43,2 секунды за день).

Может получиться так, что вызов функции adjtime() придется на момент, когда предыдущее изменение показания часов не завершилось. В таком случае объем оставшегося неизмененного времени возвращается в timeval-структуру olddelta. Если это значение нас не интересует, для аргумента olddelta нужно указать NULL. И наоборот, если нас интересуют только сведения о текущем объеме невыполненной коррекции времени и мы не намереваемся изменять значение, в качестве аргумента delta можно указать NULL.

Несмотря на то что в SUSv3 функция adjtime() не указана, она доступна в большинстве реализаций UNIX.

В Linux функция adjtime() реализована в качестве надстройки над более универсальным (и сложным) характерным для Linux системным вызовом adjtimex(). Этот системный вызов используется резидентной программой (демоном) Network Time Protocol (NTP). Дополнительные сведения можно найти в исходном коде Linux, на странице руководства Linux adjtimex(2) и в спецификации NTP ([Mills, 1992]).

10.6. Программные часы (мгновения)

Точность различных связанных со временем системных вызовов, рассматриваемых в данной книге, ограничивается разрешением программных системных часов, которые измеряют отрезки времени в единицах, называемых мгновениями (jiffies). Размер мгновения определяется внутри исходного кода ядра константой HZ. Эта единица измерения используется ядром при выделении процессам времени центрального процессора в соответствии с циклическим алгоритмом его планирования (см. раздел 35.1).

В Linux/x86-32 в ядрах версий до 2.4 включительно частота программных часов была 100 Гц, то есть мгновение составляло 10 миллисекунд.

Поскольку со времени первой реализации Linux скорости работы центральных процессоров существенно возросли, в ядре версии 2.6.0 частота программных часов на Linux/x86-32 была поднята до 1000 Гц. Преимущество повышенной частоты программных часов заключается в том, что таймер может работать с более высокой точностью и замеры времени могут быть намного точнее. Но выводить частоту часов на слишком высокие значения нежелательно, поскольку каждое прерывание от таймера потребляет небольшой объем времени центрального процессора, которое уже невозможно потратить на выполнение процессов.