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

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

Жанры

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

Кёртен Роб

Шрифт:

Это очень важный момент. Флуктуации отсчета времени — одна из печальных жизненных реалий. Единственный способ избавиться от этой проблемы заключается в увеличении разрешающей способности так, чтобы получающиеся погрешности укладывались в пределы установленных допусков. (Как это делается, мы рассмотрим ниже, в разделе «Опрос и установка часов реального времени».). Имейте в виду, что флуктуации проявляются только на первом отсчете таймера — задержка на 100 секунд, реализуемая с помощью таймера с разрешением в 10 мс, попадет в интервал между 100 и 100.01 секундами.

Типы

таймеров

Таймер, работу которого мы только что обсудили, называют относительным таймером. Для такого таймера период ожидания задается относительно текущего времени. Если бы вы пожелали задержать выполнение вашего потока до 12 часов 4 минут 33 секунд EDT (Eastern Daylight Time — восточное поясное время — прим. ред.) 20 января 2005 года, вам пришлось бы сначала рассчитать точное число секунд от «сейчас» до выбранного вами момента и включить относительный таймер с задержкой на это число секунд. Поскольку это довольно часто встречающаяся операция, в QNX/Neutrino реализованы абсолютные таймеры, которые обеспечивают задержку до заданного времени (а не на заданное время, как в случае относительного таймера).

А что если вы захотите сделать что-нибудь полезное, пока поток ожидает наступления установленной даты? Или делать что-либо и получать «синхроимпульс» каждые 27 секунд? Здесь нельзя просто так позволить себе спать!

Как мы уже обсуждали в главе «Процессы и потоки», вы можете просто запустить другой поток, и пусть он выполняет работу, пока ваш поток спит. Однако, поскольку мы говорим сейчас о таймерах, посмотрим, как это можно сделать другим способом.

В зависимости от выбранной цели, вы можете сделать это с помощью либо периодического, либо однократного таймера. Периодический таймер — это таймер, который срабатывает периодически, уведомляя поток (снова и снова), что истек некоторый временной интервал. Однократный таймер — это таймер, который срабатывает только один раз.

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

Однако, вместо удаления из очереди на выполнение после системного вызова, на этот раз ваш поток продолжит работу. И в момент, когда суточное время достигнет заданного вами и хранимого в памяти момента времени, ядро уведомит ваш поток о том, что назначенное время пришло.

Схема уведомления

Как получить уведомление о тайм-ауте? При использовании таймера задержки вы получаете уведомление просто посредством возвращения в состояние READY.

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

• послать импульс;

• послать сигнал:

• создать поток.

Импульсы мы уже обсуждали главе «Обмен сообщениями»; сигналы — стандартный для UNIX механизм. Здесь же мы кратко рассмотрим уведомления при помощи создания потока.

Как заполнять структуру struct sigevent

Независимо от выбранной вами схемы уведомления, вам обязательно придется заполнять структуру

struct sigevent
. Давайте вкратце посмотрим, как это делается.

struct sigevent {

 int sigev_notify;

 union {

int sigev_signo;

int sigev_coid;

int sigev_id;

void (*sigev_notify_function)(union sigval);

 };

 union sigval sigev_value;

 union {

struct {

short sigev_code;

short sigev_priority;

};

pthread_attr_t *sigev_notify_attributes;

 };

};

Обратите
внимание, что в приведенной декларации используются неименованные объединения и структуры. Внимательное изучение файла заголовка покажет вам, как этот трюк проходит с компиляторами, не поддерживающими такую особенность. По существу там есть директива
#define
, которая заставляет именованные объединения и структуры выглядеть неименованными. Подробнее см.
<sys/siginfo.h>
.

Первое поле, которое вы должны заполнить, — это элемент sigev_notify, который определяет выбранный вами тип уведомления:

SIGEV_PULSE

Будет передан импульс.

SIGEV_SIGNAL, SIGEV_ SIGNAL _CODE или SIGEV_SIGNAL_THREAD

Будет передан сигнал.

SIGEV_UNBLOCK

В данном случае не используется; предназначен для тайм-аутов ядра (см. ниже в разделе «Тайм-ауты ядра»).

SIGEV_INTR

В данном случае не используется; предназначен для прерываний (см. главу «Прерывания»),

SIGEV_THREAD

Будет создан поток.

Поскольку мы намерены использовать структуру

struct sigevent
для таймеров, нас будут интересовать только такие значения sigev_notify как SIGEV_PULSE, SIGEV_SIGNAL* и SIGNAL_THREAD; остальные мы рассмотрим в соответствующих их применению разделах.

Уведомление при помощи импульса

Чтобы передать импульс при срабатывании таймера, присвойте полю sigev_notify значение SIGEV_PULSE и обеспечьте немного дополнительной информации:

Поле Значение и смысл
sigev_coid Идентификатор соединения (connection ID), по каналу которого которому будет передан импульс.
sigev_value 32-разрядное значение (данные импульса — см. параграф «Что внутри импульса?», глава «Обмен сообщениями» — прим. ред.), которое будет передано по заданному полем sigev_coid соединению.
sigev_code 8-разрядное значение (код импульса — см. параграф «Что внутри импульса?», глава «Обмен сообщениями» — прим. ред.), которое будет передано по заданному полем sigev_coid соединению.
sigev_priority Приоритет доставки импульса. Нулевое значение не допускается — слишком уж много людей пострадало от переключения на нулевой приоритет после получения импульса, а поскольку на этом приоритете приходится конкурировать за процессор со спецпроцессом IDLE, много процессорного времени там точно не светит :-).
Поделиться:
Популярные книги

Я снова не князь! Книга XVII

Дрейк Сириус
17. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я снова не князь! Книга XVII

На границе империй. Том 10. Часть 2

INDIGO
Вселенная EVE Online
Фантастика:
космическая фантастика
5.00
рейтинг книги
На границе империй. Том 10. Часть 2

Маяк надежды

Кас Маркус
5. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Маяк надежды

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

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

Бастард Императора. Том 8

Орлов Андрей Юрьевич
8. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 8

Первый среди равных. Книга III

Бор Жорж
3. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
6.00
рейтинг книги
Первый среди равных. Книга III

Восход. Солнцев. Книга I

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

На границе империй. Том 7. Часть 5

INDIGO
11. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 7. Часть 5

Real-Rpg. Еретик

Жгулёв Пётр Николаевич
2. Real-Rpg
Фантастика:
фэнтези
8.19
рейтинг книги
Real-Rpg. Еретик

Отмороженный 3.0

Гарцевич Евгений Александрович
3. Отмороженный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Отмороженный 3.0

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

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

СД. Том 13

Клеванский Кирилл Сергеевич
13. Сердце дракона
Фантастика:
фэнтези
6.55
рейтинг книги
СД. Том 13

Хорошая девочка

Кистяева Марина
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Хорошая девочка

Вторая жизнь майора. Цикл

Сухинин Владимир Александрович
Вторая жизнь майора
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Вторая жизнь майора. Цикл