rtc(4) часы реального времени

ОБЗОР

#include <linux/rtc.h>

int ioctl(fd, RTC_request, param);

ОПИСАНИЕ

Данное устройство представляет собой интерфейс к драйверам часов реального времени (RTC).

В большинстве компьютеров есть одни и более аппаратных часов, ведущих отчёт "обычного" времени. Они называются "часами реального времени" (Real Time Clock, RTC). Некоторые из них имеют батарею резервного питания для продолжения работы в периоды, когда компьютер выключен. В RTC часто встроены будильники и другие прерывания.

Все ПК i386 и системы с ACPI содержат RTC, которые совместимы с микросхемой Motorola MC146818 из первоначальной модели PC/AT. Сегодня такие RTC обычно встраивают в чипсет материнской платы (в южный мост), и они используют заменяемую резервную батарею (типа «таблетки»).

В системах, несовместимых с PC (например, встраиваемые системы, собираемые на процессоре "всё в одном"), используются другие варианты. Обычно, они не предоставляют таких возможностей, как RTC в PC/AT.

RTC и системные часы

Не нужно путать RTC с системными часами, которые представляют собой часы, реализованные в ядре программно и используемые для работы gettimeofday(2) и time(2), а также при указании временных меток файлов и т. п. Системные часы выдают секунды и микросекунды, начиная отсчёт от эпохи POSIX: 1970-01-01 00:00:00 +0000 (UTC) (в основном, реализуется на основе таймера прерываний ведя подсчёт «мигов» (jiffy) c частотой 100, 250 или 1000 Гц). То есть, предполагается, что они показывают обычное время как и RTC.

Ключевым отличием RTC от системных часов, является то, что RTC работают даже когда система находится в состоянии пониженного энергопотребления (даже в выключенном), а для системных часов такое недоступно. До своей инициализации системные часы показывают время, прошедшее с момента запуска системы, а не с начала эпохи POSIX. Поэтому при загрузке и после восстановления из состояния пониженного энергопотребления в системных часах часто подстраивают текущее время с помощью RTC. Системам без RTC требуется установить свои системные часы с помощью других часов, возможно через сеть или ручного ввода данных.

Назначение RTC

Из RTC можно читать или писать с помощью hwclock(8) или через вызовы ioctl, перечисленные ниже.

Помимо контроля даты и времени многие RTC также позволяют генерировать прерывания

*
при каждом обновлении часов (т.е. раз в секунду);
*
через периодические интервалы с частотой, значение которой может быть любой степенью 2 в диапазоне от 2 Гц до 8192 Гц;
*
по достижению указанного времени будильника.

Каждый из этих источников прерываний можно включать или выключать независимо друг от друга. Во многих системах прерывание будильника можно настроить как событие пробуждения системы, для вывода системы из состояний пониженного энергопотребления таких как: ждущего режима (Suspend-to-RAM (STR), S3 в терминологии ACPI), спящего режима (hibernation, S4 в терминологии ACPI) или даже из "выключенного" состояния (S5 в терминологии ACPI). Но в некоторых системах RTC с резервной батареей не могут генерировать прерывания.

Устройство /dev/rtc (или /dev/rtc0, /dev/rtc1 и т.д.) можно открыть только один раз (до тех пор, пока не будет закрыто) и только для чтения. При вызове read(2) и select(2) вызывающий процесс блокируется до следующего приёма прерывания от RTC. После прерывания процесс может прочитать длинное целое, в котором наименее значимый байт содержит битовую маску типа произошедшего прерывания, а остальные 3 байта содержат количество прерываний, произошедших с последнего вызова read(2).

Интерфейс ioctl(2)

Для файловых дескрипторов, указывающих на открытые устройства RTC, доступны следующие запросы ioctl(2):
RTC_RD_TIME
Получить время RTC в виде следующей структуры:
struct rtc_time {
    int tm_sec;
    int tm_min;
    int tm_hour;
    int tm_mday;
    int tm_mon;
    int tm_year;
    int tm_wday;     /* не используется */
    int tm_yday;     /* не используется */
    int tm_isdst;    /* не используется */
};
Поля структуры имеют те же значения и диапазоны что и у структуры tm, описанной в gmtime(3). Указатель на эту структуру должен передаваться в третьем аргументе ioctl(2).
RTC_SET_TIME
Установить время RTC в значение, заданное в структуре rtc_time, на которую указывает третий аргумент ioctl(2). Для установки времени RTC процесс должен иметь права (т.е., мандат CAP_SYS_TIME).
RTC_ALM_READ, RTC_ALM_SET
Получить и установить время будильника, если он поддерживается RTC. Прерывание будильника должно быть включено или выключено отдельно с помощью запросов RTC_AIE_ON, RTC_AIE_OFF. Третий аргумент ioctl(2) является указателем на структуру rtc_time. В структуре используются только поля tm_sec, tm_min и tm_hour.
RTC_IRQP_READ, RTC_IRQP_SET
Получить и установить частоту периодических прерываний, если они поддерживаются RTC. Периодическое прерывание должно быть включено или выключено отдельно с помощью запросов RTC_PIE_ON, RTC_PIE_OFF. Третий аргумент ioctl(2) имеет тип unsigned long * или unsigned long, соответственно. Значение задаёт частоту прерываний в секунду. Можно указывать частоты кратны степени 2 в диапазоне от 2 до 8192. Только привилегированный процесс (т.е., имеющий мандат CAP_SYS_RESOURCE) может устанавливать частоты выше значения, указанного в /proc/sys/dev/rtc/max-user-freq. (По умолчанию в этом файле содержится значение 64.)
RTC_AIE_ON, RTC_AIE_OFF
Включить или выключить прерывание от будильника, если RTC поддерживает будильники. Третий аргумент ioctl(2) игнорируется.
RTC_UIE_ON, RTC_UIE_OFF
Включить или выключить прерывание при каждом обновлении часов, если RTC поддерживает создание прерываний один раз в секунду. Третий аргумент ioctl(2) игнорируется.
RTC_PIE_ON, RTC_PIE_OFF
Включить или выключить периодическое прерывание, если RTC поддерживает периодические прерывания. Третий аргумент ioctl(2) игнорируется. Только привилегированный процесс (т.е., имеющий мандат CAP_SYS_RESOURCE) может устанавливать частоты выше значения, указанного в /proc/sys/dev/rtc/max-user-freq.
RTC_EPOCH_READ, RTC_EPOCH_SET
В многих RTC год кодируется в 8-битном регистре, значение которого может учитываться как 8-битное двоичное число или как число в двоично-десятичном коде (BCD). В обоих случаях, число учитывается относительно начала эпохи RTC. Эпоха RTC на большинстве систем начинается с 1900 года, но на Alpha и MIPS также она может начинаться с 1952, 1980 или 2000 года, в зависимости от значения годового регистра RTC. С некоторыми RTC эти операции можно использовать для чтения или установки эпохи RTC, соответственно. Третий аргумент ioctl(2) имеет тип unsigned long * или unsigned long, соответственно, а возвращаемое значение (или назначаемое) является эпохой. Чтобы установить эпоху RTC процесс должен быть привилегированным (т.е., иметь мандат CAP_SYS_TIME).
RTC_WKALM_RD, RTC_WKALM_SET
Некоторые RTC поддерживают более универсальный интерфейс будильника, в котором эти ioctl используются для чтения и записи времени будильника RTC (соответственно) с помощью структуры:

struct rtc_wkalrm {
    unsigned char enabled;
    unsigned char pending;
    struct rtc_time time;
};
Флаг enabled используется для включения или отключения прерывания будильника, или для чтения его текущего состояния; когда совершаются данные вызовы RTC_AIE_ON и RTC_AIE_OFF не используются. Флаг pending используется RTC_WKALM_RD для сообщения об ожидающем прерывании (хотя это практически бесполезно в Linux, за исключением RTC, управляемого микропрограммой EFI). Поле time используется RTC_ALM_READ и RTC_ALM_SET, но поля tm_mday, tm_mon и tm_year также учитываются. Указатель на эту структуру должен передаваться в третьем аргументе ioctl(2).

ФАЙЛЫ

/dev/rtc, /dev/rtc0, /dev/rtc1 и т.д.: специальные файлы символьных устройств RTC.

/proc/driver/rtc: состояние (первого) RTC.

ЗАМЕЧАНИЯ

Когда системное время ядра синхронизируется с внешним источником с помощью adjtimex(2), оно будет обновляться назначенным RTC с периодичностью каждые 11 минут. Для этого ядро на время отключает периодические прерывания; это может повлиять на программы, использующие RTC.

Эпоха RTC не имеет ничего общего с эпохой POSIX, которая используется только в системных часах.

Если год, согласно эпохи RTC и регистр года меньше чем 1970, то предполагается, что время на 100 лет позже, то есть, между 2000 и 2069 годами.

Некоторые RTC поддерживают значения «шаблона» в полях будильника, чтобы обеспечить поддержку сценариев, например периодические будильники, через первые 15 минут в начале каждого часа, или первый день каждого месяца. Но это непереносимо; переносимый код пользовательского пространства только ожидает единичное прерывание от будильника, и будет или отключать, или реинициализировать будильник после приёма.

Некоторые RTC поддерживают периодические прерывания с периодами кратными степени 2, а не дробной секунде; несколько будильников; программируемые выходные сигналы часов; энергонезависимую память; другие аппаратные свойства, для которых пока ещё не предусмотрено программного интерфейса.