Читайте также:
|
|
Цель работы: изучение, оценка погрешности и практическое применение
способов задания и измерения временных интервалов в ОС QNX.
Операционная система жесткого реального времени QNX Neutrino предназначена для встраиваемых систем. Такие системы обычно работают в автономном режиме и не требуют администрирования. Однако при проектировании аппаратуры автоматических управляющих систем и разработке программного обеспечения для них необходимо глубоко изучить и грамотно использовать все свойства операционной системы и пользовательских приложений для неё.
В настоящее время многие разработчики операционных систем представляют свой программный продукт как системы реального времени. В такой спорной ситуации только экспериментальная проверка операционных систем по минимальной величине времени реакции на запросы прерываний от событий во внешней среде позволяют выявить настоящие операционные системы реального
времени (ОС РВ – OS RTP). Из всех многозадачных ОС только QNX является
операционной системой реального времени и это определяется её уникальной
архитектурой.
Поведение ОС после системных вызовов и наступления событий должно
быть предсказуемо и известно заранее. Это означает, что разработчики ОС
должны специфицировать такие временные характеристики, как «задержка обработки прерывания» (interrupt latency), максимальное время маскировки прерываний, а также максимальное время исполнения всех системных вызовов.
Фиксация временных интервалов (например, тайм-ауты, тайм-ауты ядра, интервальные таймеры) и хронометраж выполнения участков кода для ОС реального времени QNX RTP на порядок более критичны, чем для GPOS (General
Purpose Operation System) – универсальных OS общего применения, например,
для всего семейства Windows.
Задание любых временных интервалов во всех операционных системах выполняется с использованием функций sleep(), usleep(), nanosleep(),
delay(), alarm(), select(), nanospin(), sigaction(). Применяются и функции, связанные с созданием и использованием интервальных таймеров – все
функции группы timer_*().
Измерение временных характеристик выполнения (хронометрирование) критических участков программного кода производится с использованием, например, функций clock(), time(), times().
Поведение службы времени QNX определяется реализацией следующих
принципов:
· микроядро QNX использует дискретную сетку времени;
· каждый единичный момент времени для микроядра – это такт или «тик»
системного времени (timeslice). Какие-либо изменения состояний времени фиксируются микроядром только в узлах этой дискретной шкалы времени;
· микроядро «не различает» или «не разрешает» два временных события, если они происходят между соседними «тиками» системного времени с интервалом, меньшим, чем интервал системного тика.
Начальная (после загрузки системы) длительность тика определяется соглашениями, принятыми для той или иной версии QNX. В документации сказано,
что для QNX RTP 6.1 при тактовой частоте процессора >40МГц тик составляет
1мс, и 10 мс – при меньших частотах процессора. Значение тика для QNX RTP
6.1 программно может быть переустановлено вызовом ClockPeriod(), но не
точнее 500 мксек. Для QNX Momentics 6.2.1 (последняя стабильная версия) значение системного тика по умолчанию – 1 мсек., а минимальное значение системного тика может быть установлено в 10 мксек.
В архитектуре PC x86 часы реального времени работают от задающего кварцевого генератора, сигнал от которого далее поступает на делитель. Из-за различий в 5–6 знаке (коэффициент деления должен быть целым числом) реально
период тика чуть меньше 1мсек для значения, установленного по умолчанию
или чуть меньше переустанавливаемого значения. Чтение значения системного тика представлено в Листинге 1:
Листинг 1
_clockperiod clcold;
ClockPeriod(CLOCK_REALTIME,NULL,&clcold,0);
cout << “ClockPeriod=” << clcold.nsec <<endl;
Структура _clockperiod имеет вид:
s truct _clockperiod {
uint64_t nsec, // наносекунды
fract //фемтосекунды,рассчитано на будущие
// развитие и должно быть равным 0!
};
Стандарт POSIX 1003.1b–1993/1003.1i-1995 (расширение POSIX для реального времени) требует, чтобы все детерминированные на временной шкале события, например, такие как завершения ожидания и тайм-ауты, наступали не
раньше истечения установленного временного интервала. Таким образом,
POSIX накладывает ограничения только «снизу», поэтому, естественно, что и
единица шкалы измерения величин размерности «время» может быть несколько
менее 1 мсек., тогда результат измерения будет несколько больше ожидаемого
значения. В Листинге 2 рассматривается переустановка значения системного тика:
rfr
Листинг 2
Const int TICK=500000;
_clockperiod clcnew={TICK,0},clcold;
ClockPeriod(CLOCK_REALTIME, &clcnew, &clcold,0); //переустановить
ClockPeriod(CLOCK_REALTIME, NULL, &clcold,0); //проверить
cout << “ClockPeriod=” << clcold.nsec <<endl;
В документации QNX утверждается, что «при попытках установить значение
ниже минимального предела, будет установлено стандартное системное значение». Реально при попытке установить TICK меньше нижней границы в системе
QNX 6.х будет сохранено последнее установленное в системе значение тика.
После завершения процедуры, которая производит переустановку системного
тика, все временные масштабы в системе будут изменены. Лучшее решение в
этой ситуации состоит в том, чтобы в любой задаче, изменяющей системный
тик, перед завершением восстанавливать значение, сохраненное при её старте.
«Абсолютное» время с высокой точностью в экспериментах можно определять и задавать с использованием аппаратного 64-разрядного счётчика периодов частоты синхронизации процессоров семейства х86, начиная с х = 5.
Текст программы, в которой выполняется исследование некоторых функций
службы времени, приведён в Листинге 3.
Листинг 3
#include <stdio.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>
#include <inttypes.h>
#include <unistd.h>
const int TICK = 100000;
int main(int argc, char *argv[], char *envp[])
{
_clockperiod clcold, clcnew = { TICK, 0 }, clcdown;
ClockPeriod(CLOCK_REALTIME, NULL, &clcold, 0);
printf("\Current ClockPeriod = %u nsec\n", clcold.nsec);
ClockPeriod(CLOCK_REALTIME, &clcnew, &clcold, 0);
ClockPeriod(CLOCK_REALTIME, NULL, &clcold, 0);
printf("Expected ClockPeriod = %lu nsec\n", TICK);
printf("New ClockPeriod = %lu nsec\n", clcold.nsec);
uint64_t cps = SYSPAGE_ENTRY(qtime)->cycles_per_sec;
printf("\nCPU Frequency = %lu Hz\n", cps);
uint64_t beg = ClockCycles();
for(int i=0; i<=999; i++)
delay(1);
uint64_t fin=ClockCycles();
uint64_t delta = fin - beg;
printf("\nAbsolute time of 1000*delay(1) = %lu nsec, ", delta);
printf("ClockPeriod = %lu nsec\n", clcold.nsec);
beg = ClockCycles();
delay(1000);
fin = ClockCycles();
delta = fin - beg;
printf("\nAbsolute time of delay(1000) = %lu nsec, ", delta);
printf("ClockPeriod = % lu nsec\n", clcold.nsec);
beg = ClockCycles();
sleep(1);
fin = ClockCycles();
delta = fin - beg;
printf("\nAbsolute time of sleep(1) = %lu nsec, ", delta);
printf("ClockPeriod = %lu nsec\n", clcold.nsec);
ClockPeriod(CLOCK_REALTIME, &clcdown, &clcold, 0);
ClockPeriod(CLOCK_REALTIME, NULL, &clcold, 0);
printf("\nSet up previous ClockPeriod = %u nsec\n", clcold.nsec);
beg = ClockCycles();
for(int i=0; i<=999; i++)
delay(1);
fin = ClockCycles();
delta = fin - beg;
printf("\nAbsolute time of 1000*delay(1) = %lu nsec, ", delta);
printf("ClockPeriod = %lu nsec\n", clcold.nsec);
beg = ClockCycles();
delay(1000);
fin = ClockCycles();
delta = fin - beg;
printf("\nAbsolute time of delay(1000) = %lu nsec, ", delta);
printf("ClockPeriod = % lu nsec\n", clcold.nsec);
beg = ClockCycles();
sleep(1);
fin = ClockCycles();
delta = fin - beg;
printf("\nAbsolute time of sleep(1) = %lu nsec, ", delta);
printf("ClockPeriod = %lu nsec\n", clcold.nsec);
return 0;
}
С помощью встроенного текстового редактора набрать текст программы из Листинга 3, компилировать и выполнить эту программу, записав в файл результаты работы программы для последующего включения в отчёт по работе. Во время выполнения работы можно пользоваться системой помощи Help, в которой содержится исчерпывающая информация по всей ОС и которая оснащена простой в использовании подсистемой поиска. Результат работы программы представлен на рисунке 1.
Содержание работы
1. Открыть QNX Momentics IDE;
2. Создать новый C++ проект QNX, задать название и выбрать целевую архитектуру x86;
3. Набрать код из Листинга 1;
4. Построить проект (Project - Rebuild All);
5. Запустить программу и оценить выводимые на экран результаты её работы;
6. Выполнить пп. 4, 5 несколько раз, задавая различные значения const int TICK в диапазоне от 50000 до 500000;
7. Выбор значений const int TICK следует выполнять с учётом того, что при некоторых, достаточно малых значениях ОС QNX должна «повиснуть».
8.[1] Составить программу для измерения временных интервалов с помощью функции times() – POSIX 1003.1
Контрольные вопросы:
1. Каковы основные принципы работы службы времени в ОСРВ QNX?
2. Допустимы ли отличия в меньшую сторону реального значения системного такта от заданного и почему?
3. Стандарт POSIX. Что в себя включает данный стандарт?
4. Какое назначение у функции ClockPeriod, и какие у нее аргументы?
5. Какие существуют способы измерения временных интервалов в ОС QNX?
6. Почему результаты измерений при использовании разных способов задания интервалов ожидания и при задании разных значений системного такта отличаются?
[1] Дополнительное задание
Дата добавления: 2015-11-14; просмотров: 127 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Experiment 3. Qualitative reactions to vitamin С (ascorbic acid). | | | Oh, this is the LIFE! |