Ядро предоставляет системный вызов time()
[58] ля некоторых аппаратных платформ функция sys_time() не реализована, а вместо этого она эмулируется библиотекой функций языка С на основании вызова gettimeofday() .
, однако системный вызов gettimeofday()
полностью перекрывает его возможности. Библиотека функций языка С также предоставляет другие функции, связанные с абсолютным временем, такие как ftime()
и ctime()
.
Системный вызов settimeofday()
позволяет установить абсолютное время в указанное значение. Для того чтобы его выполнить, процесс должен иметь возможность использования CAP_SYS_TIME
.
Если не считать обновления переменной xtime
, то ядро не так часто использует абсолютное время, как пространство пользователя. Одно важное исключение— это код файловых систем, который хранят в индексах файлов значения моментов времени доступа к файлам.
Таймеры (timers), или, как их еще иногда называют, динамические таймеры , или таймеры ядра , необходимы для управления ходом времени в ядре. Коду ядра часто необходимо откладывать выполнение некоторых функций на более позднее время. Здесь намеренно выбрано не очень четкое понятие " позже ". Назначение механизма нижних половин — это не задерживать выполнение, а не выполнять работу прямо сейчас . В связи с этим необходим инструмент, который позволяет задержать выполнение работы на некоторый интервал времени. Если этот интервал времени не очень маленький, но и не очень большой, то решение проблемы — таймеры ядра.
Таймеры очень легко использовать. Необходимо выполнить некоторые начальные действия, указать момент времени окончания ожидания, указать функцию, которая будет выполнена, когда закончится интервал времени ожидания, и активизировать таймер. Указанная функция будет выполнена, когда закончится интервал времени таймера. Таймеры не являются циклическими. Когда заканчивается интервал времени ожидания, таймер ликвидируется. Это одна из причин, почему таймеры называют динамическими [59] Другая причина состоит в том, что в ядрах старых версий (до 2.3) существовали статические таймеры. Такие таймеры создавались во время компиляции, а не во время выполнения. Они имели ограниченные возможности и из-за их отсутствия сейчас никто не огорчается.
. Таймеры постоянно создаются и ликвидируются, на количество таймеров не существует ограничений. Использование таймеров очень популярно во всех частях ядра.
Таймеры представлены с помощью структур timer_list
, которая определена в файле следующим образом.
struct timer_list {
struct list_head entry; /* таймеры хранятся в связанном списке */
unsigned long expires; /* время окончание срока ожидания в
импульсах системного таймера (jiffies) */
spinlock_t lock; /* блокировка для защиты данного таймера */
void (*function)(unsigned long); /*функция-обработчик таймера */
unsigned long data; /* единственный аргумент обработчика */
struct tvec_t_base_s *base; /* внутренние данные таймера, не трогать! */
};
К счастью, использование таймеров не требует глубокого понимания назначения полей этой структуры. На самом деле, крайне не рекомендуется использовать поля этой структуры не по назначению, чтобы сохранить совместимость с возможными будущими изменениями кода. Ядро предоставляет семейство интерфейсов для работы с таймерами, чтобы упростить эту работу. Все необходимые определения находятся в файле . Большинство реализаций находится в файле kernel/timers
.
Первый шаг в создании таймера — это его объявление в следующем виде.
struct timer_list my_timer;
Далее должны быть инициализированы поля структуры, которые предназначены для внутреннего использования. Это делается с помощью вспомогательной функции перед вызовом любых функций, которые работают с таймером.
init_timer(&my_timer);
Далее необходимо заполнить все остальные поля структуры, например, следующим образом.
my_timer.expires = jiffies + delay; /* интервал времени таймера
закончится через delay импульсов */
my_timer.data = 0; /* в функцию-обработчик будет передан параметр,
равный нулю */
my_timer.function = my_function; /* функция, которая будет выполнена,
когда интервал времени таймера истечет */
Значение поля my_timer.expires
указывает время ожидания в импульсах системного таймера (необходимо указывать абсолютное количество импульсов). Когда текущее значение переменной jiffies
становится большим или равным значению поля my_timer.expires
, вызывается функция-обработчик my_timer.function
с параметром my_timer.data
. Как видно из описания структуры timer_list
, функция-обработчик должна соответствовать следующему прототипу.
Читать дальше