Использование таймеров

Использование таймеров

Таймеры представлены с помощью структур timer_list, которая определена в файле <linux/timer.h> следующим образом.

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; /* внутренние данные таймера, не трогать! */

};

К счастью, использование таймеров не требует глубокого понимания назначения полей этой структуры. На самом деле, крайне не рекомендуется использовать поля этой структуры не по назначению, чтобы сохранить совместимость с возможными будущими изменениями кода. Ядро предоставляет семейство интерфейсов для работы с таймерами, чтобы упростить эту работу. Все необходимые определения находятся в файле <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() не может вызываться из контекста прерывания.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Использование SCM

Из книги Сущность технологии СОМ. Библиотека программиста автора Бокс Дональд

Использование SCM Напомним, что SCM поддерживает три примитива активации (связывание с объектами класса, связывание с экземплярами класса, связывание с постоянными экземплярами из файлов). Как показано на рис. 3.2, эти примитивы логически разделены на уровни[1]. Примитивом


3.1.3. Использование yum

Из книги Fedora 8 Руководство пользователя автора Колисниченко Денис Николаевич

3.1.3. Использование yum Управлением пакетами в Fedora занимается программа yum (Yellow dog Updater Modified) - это и есть менеджер пакетов. С его помощью вы можете устанавливать и удалять пакеты, а также обновлять уже установленные пакеты.Программа yum не обладает графическим интерфейсом,


3.3.3. Использование RPM

Из книги Язык программирования С# 2005 и платформа .NET 2.0. [3-е издание] автора Троелсен Эндрю

3.3.3. Использование RPM Программа RPM не имеет графического интерфейса, поэтому запускать ее нужно в консоли или в терминале (команда меню Приложения?Системные?Терминал). Формат вызова программы rpm следующий:rpm [-опции] [пакеты]Напомню, что установка программ - это привилегия


Программирование с помощью таймеров обратного вызова

Из книги Сетевые средства Linux автора Смит Родерик В.

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


Использование tar

Из книги Технология XSLT автора Валиков Алексей Николаевич

Использование tar Утилита tar — одна из самых популярных программ, используемых для резервного копирования в системах Linux и UNIX. Она объединяет несколько файлов в один файл архива, что упрощает передачу информации по сети и сохранение ее на резервном носителе. Название


Использование

Из книги Разработка приложений в среде Linux. Второе издание автора Джонсон Майкл К.


Использование

Из книги Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform автора Кёртен Роб

Использование Как и любой другой XSLT-процессор, написанный на Java, xt можно без труда использовать в Java-проектах. Помимо этого, xt можно использовать в качестве сервлета и из командной строки.Сервлет-версия xt реализована в классе com.jclark.xsl.sax.XSLservlet и может выполняться на


14.7.1. Использование ftw()

Из книги Программирование для Linux. Профессиональный подход автора Митчелл Марк

14.7.1. Использование ftw() #include <ftw.h>int ftw(const char *dir, ftwFunctionPointer callback, int depth);Функция ftw() начинает с каталога dir и вызывает указанную в callback функцию для каждого файла в этом каталоге и его подкаталогах. Функция вызывается для всех типов файлов, включая символические ссылки и


18.2. Использование таймеров

Из книги iOS. Приемы программирования автора Нахавандипур Вандад

18.2. Использование таймеров Таймер — это простое средство для указаний определенной точки в будущем, в которой должно произойти некоторое событие. Вместо того чтобы циклически запрашивать текущее время и проводить лишние растраты циклов центрального процессора,


Типы таймеров

Из книги Разработка ядра Linux автора Лав Роберт

Типы таймеров Таймер, работу которого мы только что обсудили, называют относительным таймером. Для такого таймера период ожидания задается относительно текущего времени. Если бы вы пожелали задержать выполнение вашего потока до 12 часов 4 минут 33 секунд EDT (Eastern Daylight Time —


Применение таймеров

Из книги автора

Применение таймеров Изучив все красоты теории, давайте теперь переключим наше внимание на конкретные образцы кода, чтобы посмотреть, что можно сделать при помощи таймеров.Чтобы работать с таймером, вам потребуется:1. Создать объект типа «таймер».2. Выбрать схему


8.13. Функция setitimer(): задание интервальных таймеров

Из книги автора

8.13. Функция setitimer(): задание интервальных таймеров Функция setitimer() является обобщением системного вызова alarm(). Она планирует доставку сигнала по истечении заданного промежутка времени.С помощью функции setitimer() можно создавать таймеры трех типов.? ITIMER_REAL. По истечении


7.14. Создание таймеров

Из книги автора

7.14. Создание таймеров Постановка задачи Требуется многократно выполнять определенную задачу после заданной задержки. Например, вы хотите обновлять вид на экране устройства каждую секунду, пока работает ваше


7.17. Выход из потоков и таймеров

Из книги автора

7.17. Выход из потоков и таймеров Постановка задачи Требуется остановить поток или таймер либо не допустить его повторного


Использование таймеров

Из книги автора

Использование таймеров Таймеры представлены с помощью структур timer_list, которая определена в файле <linux/timer.h> следующим образом.struct timer_list { struct list_head entry; /* таймеры хранятся в связанном списке */ unsigned long expires; /* время окончание срока ожидания в                         


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

Из книги автора

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