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

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

Жанры

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

Кёртен Роб

Шрифт:
Функция Тип Описание
ClockAdjust QNX/Neutrino Плавная регулировка времени
ClockCycles QNX/Neutrino Опрос с высоким разрешением
clock_getres POSIX Выборка базового разрешения
clock_gettime POSIX Получение текущего времени суток
ClockPeriod QNX/Neutrino Получение/установка
базового разрешения
clock_settime POSIX Установка текущего времени суток
ClockTime QNX/Neutrino Получение/установка текущего времени суток
Опрос и установка

Функции clock_gettime и clock_settime являются POSIX-функциями, основанными на системном вызове ClockTime. Эти функции могут применяться для получения и установки текущего времени суток. К сожалению, установка здесь является «жесткой», то есть независимо от того, какое время вы указываете в буфере, оно немедленно делается текущим. Это может иметь пугающие последствия, особенно когда получается, что время «повернуло вспять», потому что устанавливаемое время оказалось меньше «реального». Вообще настройка часов таким способом должна выполняться только при включении питания или когда время сильно не соответствует «реальному».

Если нужна плавная корректировка текущего времени, ее можно реализовать с помощью функции ClockAdjust:

int ClockAdjust(clockid_t id,

 const struct _clockadjust *new,

 const struct _clockadjust *old);

Параметрами здесь являются источник синхроимпульсов (всегда используйте CLOCK_REALTIME) и параметры new и old. Оба эти параметра являются необязательными и могут быть заданы как NULL. Параметр old просто возвращает текущую корректировку. Работа по корректировке часов управляется параметром new, который является указателем на структуру, содержащую два элемента, tick_nsec_inc и tick_count. Действует функция ClockAdjust очень просто — каждые tick_count отсчетов системных часов к существующему значению системного времени добавляется корректировка tick_nsec_inc. Это означает, что чтобы передвинуть время вперед («догоняя» реальное), вы задаете для tick_nsec_inc положительное значение. Заметьте, что не надо переводить время назад — вместо этого, если ваши часы спешат, задайте для tick_nsec_inc небольшое отрицательное значение, и ваши часы соответственно замедлят ход. Таким образом, вы немного замедляете часы, пока их показания не будут соответствовать действительности. Существует эмпирическое правило, гласящее, что не следует корректировать системные часы значением, превышающим 10% от базового разрешения вашей системы (см. функцию ClockPeriod и ее друзей, о них мы поговорим в следующем параграфе).

Регулировка разрешающей способности

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

int ClockPeriod(clockid_t id,

 const struct _clockperiod *new,

 struct _clockperiod *old, int reserved);

Как и в случае с описанной выше функцией ClockAdjust, с помощью параметров new и old вы получаете и/или устанавливаете значения базовой разрешающей способности по времени. Параметры new и old являются указателями на структуры типа

struct _clockperiod
, которые, в свою очередь, содержат два элемента — nsec и fract. На настоящий момент элемент fract должен быть равен нулю (это число фемтосекунд (миллиардная доля микросекунды — прим. ред.); нам, вероятно, это еще не скоро потребуется). Параметр nsec
указывает, сколько наносекунд содержится в интервале между двумя базовыми отсчетами времени. Значение этого интервала времени по умолчанию — 10 миллисекунд, поэтому значение nsec (если вы используете функцию для получения базового разрешения) будет приблизительно равно 10 миллионам наносекунд. (Как мы уже упоминали ранее в разделе «Источники прерываний таймера», это не будет в точности равняться 10 миллисекундам.)

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

Точные временные метки

Существует одна система отсчета времени, которая не подчиняется описанным выше правилам «базовой разрешающей способности по времени». Некоторые процессоры оборудованы встроенным высокочастотным (высокоточным) счетчиком, к которому QNX/Neutrino обеспечивает доступ при помощи функции ClockCycles. Например, в процессоре Pentium, работающем с частотой 200 МГц, этот счетчик увеличивается тоже с частотой в 200 МГц, и поэтому он может обеспечить вам значение времени с точностью до 5 наносекунд. Это особенно полезно, когда вы хотите точно выяснить, сколько времени затрачивается на выполнение конкретного фрагмента кода (в предположении, конечно, что он не будет вытеснен). В этом случае вы должны вызвать функцию ClockCycles перед началом вашего фрагмента и после его окончания, а потом просто подсчитать разность полученных отсчетов. Более подробно это описано в руководстве по Си-библиотеке.

Тайм-ауты ядра

QNX/Neutrino позволяет вам получать тайм-ауты по всем блокированным состояниям. Мы обсуждали эти состояния в главе «Процессы и потоки» в разделе «Состояния потоков». Наиболее часто у вас может возникнуть потребность в этом при обмене сообщениями: клиент, посылая сообщение серверу, не желает ждать ответа «вечно». В этом случае было бы удобно использовать тайм-аут ядра. Тайм-ауты ядра также полезны в сочетании с функцией pthread_join: завершения потока тоже не всегда хочется долго ждать.

Ниже приводится декларация для функции TimerTimeout, которая является системным вызовом, ответственным за формирование тайм-аутов ядра.

#include <sys/neutrino.h>

int TimerTimeout(clockid_t id, int flags,

 const struct sigevent *notify,

 const uint64_t *ntime, uint64_t *otime);

Видно, что функция TimerTimeout возвращает целое число (индикатор удачи/неудачи; 0 означает, что все в порядке, -1 — что произошла ошибка, и ее код записан в errno). Источник синхроимпульсов (CLOCK_REALTIME, и т.п.) указывается в id, параметр flags задает соответствующее состояние (или состояния). Параметр notify всегда должен быть событием уведомления типа SIGEV_UNBLOCK; параметр ntime указывает относительное время, спустя которое ядро должно сгенерировать тайм-аут. Параметр otime показывает предыдущее значение тайм-аута и в большинстве случаев не используется (вы можете передать вместо него NULL).

Важно отметить, что тайм-ауты «взводятся» функцией TimerTimeout, а запускаются по входу в одно из состояний, указанных в параметре flags. Сбрасывается тайм-аут при возврате из любого системного вызова. Это означает, что вы должны заново «взводить» тайм-аут перед каждым системным вызовом, к которому вы хотите его применить. Сбрасывать тайм-аут после системного вызова не надо — это выполняется автоматически.

Тайм-ауты ядра и функция pthread_join

Самый простой пример для рассмотрения — это использование тайм-аута с функцией pthread_join. Вот как это можно было бы сделать:

/*

 * tt1.c

*/

#include <stdio.h>

#include <pthread.h>

#include <inttypes.h>

#include <errno.h>

#include <sys/neutrino.h>

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

Идеальный мир для Лекаря 10

Сапфир Олег
10. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 10

Бестужев. Служба Государевой Безопасности. Книга четвертая

Измайлов Сергей
4. Граф Бестужев
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бестужев. Служба Государевой Безопасности. Книга четвертая

Светлая тьма. Советник

Шмаков Алексей Семенович
6. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Светлая тьма. Советник

Лисья нора

Сакавич Нора
1. Всё ради игры
Фантастика:
боевая фантастика
8.80
рейтинг книги
Лисья нора

Калибр Личности 5

Голд Джон
5. Калибр Личности
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Калибр Личности 5

(Не)нужная жена дракона

Углицкая Алина
5. Хроники Драконьей империи
Любовные романы:
любовно-фантастические романы
6.89
рейтинг книги
(Не)нужная жена дракона

Сердце Дракона. Том 10

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

Белые погоны

Лисина Александра
3. Гибрид
Фантастика:
фэнтези
попаданцы
технофэнтези
аниме
5.00
рейтинг книги
Белые погоны

Как я строил магическую империю

Зубов Константин
1. Как я строил магическую империю
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Как я строил магическую империю

Повелитель механического легиона. Том VII

Лисицин Евгений
7. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Повелитель механического легиона. Том VII

Я князь. Книга XVIII

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

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

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

Вечный. Книга I

Рокотов Алексей
1. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга I

Отморозок 3

Поповский Андрей Владимирович
3. Отморозок
Фантастика:
попаданцы
5.00
рейтинг книги
Отморозок 3