Чтение онлайн

на главную - закладки

Жанры

Разработка ядра Linux
Шрифт:

 void (*function)(unsigned long); /*функция-обработчик таймера */

 unsigned long data; /* единственный аргумент обработчика */

 struct tvec_t_base_s *base; /* внутренние данные таймера, не трогать! */

};

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

определения находятся в файле
<linux/timer.h>
. Большинство реализаций находится в файле
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
, функция-обработчик должна соответствовать следующему прототипу.

void my_timer_function(unsigned long data);

Параметр

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

Последняя операция — это активизация таймера.

add_timer(&my_timer);

И таймер запускается! Следует обратить внимание на важность значения поля

expired
. Ядро выполняет обработчик, когда текущее значение счетчика импульсов системного таймера больше, чем указанное значение времени срабатывания таймера, или равно ему. Хотя ядро и гарантирует, что никакой обработчик таймера не будет выполняться до истечения срока ожидания таймера, тем не менее возможны задержки с выполнением обработчика таймера. Обычно обработчики таймеров выполняются в момент времени, близкий к моменту времени срабатывания, однако они могут быть отложены и до следующего импульса системного таймера. Следовательно, таймеры нельзя использовать для работы в жестком режиме реального времени.

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

mod_timer
, которая позволяет изменить момент времени срабатывания активного таймера.

mod_timer(&my_timer, jiffies + new_delay); /*
установка нового времени

срабатывания */

Функция

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

Для того чтобы деактивизировать таймер до момента его срабатывания, необходимо использовать функцию

del_timer
следующим образом.

del_timer(&my_timer);

Эта функция работает как с активными, так и неактивными таймерами. Если таймер уже неактивен, то функция возвращает значение 0, в другом случае возвращается значение 1. Следует обратить внимание, что нет необходимости вызывать эту функцию для таймеров, интервал ожидания которых истек, так как они автоматически деактивизируются.

При удалении таймеров потенциально может возникнуть состояние конкуренции. Когда функция

del_timer
возвращает управление, она гарантирует только то, что таймер будет неактивным (т.е. его обработчик не будет выполнен в будущем). Однако на многопроцессорной машине обработчик таймера может выполняться в этот момент на другом процессоре. Для того чтобы деактивизировать таймер и подождать, пока завершится его обработчик, который потенциально может выполняться, необходимо использовать функцию
del_timer_sync
:

del_timer_sync(&my_timer);

В отличие от функции

del_timer
, функция
del_timer_sync
не может вызываться из контекста прерывания.

Состояния конкуренции, связанные с таймерами

Так как таймеры выполняются асинхронно по отношению к выполняемому в данный момент коду, то потенциально могут возникнуть несколько типов состояний конкуренции за ресурсы. Во-первых, никогда нельзя использовать следующий код, как замену функции

mod_timer
.

del_timer(my_timer);

my_timer->expires = jiffies + new_delay;

add_timer(my_timer);

Во-вторых, практически во всех случаях следует использовать функцию

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

Наконец, необходимо гарантировать защиту всех совместно используемых дан- пых, к которым обращается функция-обработчик таймера. Ядро выполняет эту функцию асинхронно по отношению к другому коду. Совместно используемые данные должны защищаться так, как рассматривалось в главах 8 и 9.

Реализация таймеров

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

update_process_times
, которая в свою очередь вызывает функцию
run_local_timers
, имеющую следующий вид.

Поделиться:
Популярные книги

Кодекс Крови. Книга III

Борзых М.
3. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга III

Мастер темных Арканов

Карелин Сергей Витальевич
1. Мастер темных арканов
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Мастер темных Арканов

Измена. Испорченная свадьба

Данич Дина
Любовные романы:
современные любовные романы
короткие любовные романы
5.00
рейтинг книги
Измена. Испорченная свадьба

Блуждающие огни

Панченко Андрей Алексеевич
1. Блуждающие огни
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
Блуждающие огни

Пышка и Герцог

Ордина Ирина
Фантастика:
юмористическое фэнтези
историческое фэнтези
фэнтези
5.00
рейтинг книги
Пышка и Герцог

Затерянные земли или Великий Поход

Михайлов Дем Алексеевич
8. Господство клана Неспящих
Фантастика:
фэнтези
рпг
7.89
рейтинг книги
Затерянные земли или Великий Поход

Адвокат Империи 2

Карелин Сергей Витальевич
2. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 2

Газлайтер. Том 6

Володин Григорий
6. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 6

Часовая битва

Щерба Наталья Васильевна
6. Часодеи
Детские:
детская фантастика
9.38
рейтинг книги
Часовая битва

Невеста снежного демона

Ардова Алиса
Зимний бал в академии
Фантастика:
фэнтези
6.80
рейтинг книги
Невеста снежного демона

Законы Рода. Том 3

Flow Ascold
3. Граф Берестьев
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 3

Случайная свадьба (+ Бонус)

Тоцка Тала
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Случайная свадьба (+ Бонус)

Болотник 2

Панченко Андрей Алексеевич
2. Болотник
Фантастика:
попаданцы
альтернативная история
6.25
рейтинг книги
Болотник 2

Пипец Котенку! 2

Майерс Александр
2. РОС: Пипец Котенку!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Пипец Котенку! 2