- •2. Ядра и операционные системы реального времени
- •2.1. Задачи, процессы, потоки
- •2.2. Основные свойства задач
- •2.3. Планирование задач
- •2.4. Синхронизация задач
- •2.5. Тестирование
- •2.6. Можно ли обойтись без ОС РВ?
- •3. Обзор некоторых операционных систем реального времени
- •3.1. Linux реального времени
- •3.2. Операционные системы реального времени и Windows
- •3.3. Операционная система QNX
- •3.4. Проект Neutrino
- •4.1. Организация промышленных систем
- •4.2. Аппаратная архитектура
- •4.3. Стандарты шин
- •4.4. Технологии VME и PCI
- •4.5. Мезонинные технологии
- •4.6. Полевые системы
- •4.7. Программное обеспечение промышленных систем
- •4.8. Управление производством
- •Часть 2. ПРОЕКТИРОВАНИЕ СРВ
- •5. UML проектирование систем реального времени
- •5.1. Объектно-ориентированные методы и UML
- •5.2. Метод и нотация
- •5.3. Системы и приложения реального времени
- •6. Обзор нотации UML
- •6.1. Диаграммы UML
- •6.2. Диаграммы прецедентов
- •6.3. Нотация UML для классов и объектов
- •6.4. Диаграммы классов
- •6.5. Диаграммы взаимодействия
- •6.6. Диаграммы состояний
- •6.7. Пакеты
- •6.8. Диаграммы параллельной кооперации
- •6.9. Диаграммы развертывания
- •6.10. Механизмы расширения UML
- •7.1. Среды для параллельной обработки
- •7.2. Поддержка исполнения в мультипрограммной и мультипроцессорной средах
- •7.3. Планирование задач
- •7.4. Вопросы ввода/вывода в операционной системе
- •7.6. Технология World Wide Web
- •7.7. Сервисы распределенных операционных систем
- •7.8. ПО промежуточного слоя
- •7.9. Стандарт CORBA
- •7.10. Другие компонентные технологии
- •7.11. Системы обработки транзакций
- •8. Разбиение на задачи
- •8.1. Вопросы разбиения на параллельные задачи
- •8.2. Категории критериев разбиения на задачи
- •8.3. Критерии выделения задач ввода/вывода
- •8.4. Критерии выделения внутренних задач
- •8.5. Критерии назначения приоритетов задачам
- •8.6. Критерии группировки задач
- •8.7. Пересмотр проекта путем инверсии задач
- •8.8. Разработка архитектуры задач
- •8.9. Коммуникации между задачами и синхронизация
- •8.10. Спецификация поведения задачи
- •9. Проектирование классов
- •9.1. Проектирование классов, скрывающих информацию
- •9.2. Проектирование операций классов
- •9.3. Классы абстрагирования данных
- •9.4. Классы интерфейса устройства
- •9.5. Классы, зависящие от состояния
- •9.6. Классы, скрывающие алгоритмы
- •9.7. Классы интерфейса пользователя
- •9.10. Внутренние программные классы
- •9.11. Применение наследования при проектировании
- •9.12. Примеры наследования
- •9.13. Спецификация интерфейса класса
- •10. Детальное проектирование ПО
- •10.1. Проектирование составных задач
- •10.2. Синхронизация доступа к классам
- •10.4. Логика упорядочения событий
- •11.1. Теория планирования в реальном времени
- •11.2. Развитие теории планирования в реальном времени
- •11.5. Пример анализа производительности с помощью анализа последовательности событий
- •11.6. Пример анализа производительности с применением теории планирования в реальном времени
- •11.8. Пересмотр проекта
- •11.9. Оценка и измерение параметров производительности
- •12. ЗАКЛЮЧЕНИЕ
- •СПИСОК ЛИТЕРАТУРЫ
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
239 |
том – Координатором Банкомата. Когда этой задаче приходит но-
вый Запрос Управлению Банкоматом, его принимает Координатор Банкомата, который извлекает из запроса событие и вызывает опе-
рацию УправлениеБанкоматом. ОбработатьСобытие (in событие, out действие). Объект Управление Банкоматом просматривает таб-
лицу переходов, принимая во внимание текущее состояние и новое событие. Найденный элемент таблицы содержит новое состояние и действие (или действия), которое надлежит выполнить. Затем Коор- динатор Банкомата инициирует указанное действие. Если речь идет о выдаче наличных, то вызывается операция выдатьНаличные объек-
та Интерфейс Устройства Выдачи Наличных, которой в качестве входного параметра передается сумма, а в качестве выходного – ре- зультатВыдачи. Если же действие состоит в печати чека, то вызыва-
ется операция печататьЧек объекта Интерфейс Устройства Печа-
ти Чеков, которой в качестве входного параметра передается инфор-
мацияЧека, а в качестве выходного – результатПечати.
10.2. Синхронизация доступа к классам
Если к классу может обращаться несколько задач, то его опера- ции должны обеспечивать синхронизацию доступа к инкапсулируе- мым данным. Ниже описываются соответствующие механизмы: алго- ритм взаимного исключения и алгоритм нескольких читателей и пи- сателей.
10.2.1. Пример синхронизации доступа к классу. В качестве примера рассмотрим класс абстрагирования данных Хранилище По- казаний Аналоговых Датчиков. При проектировании этого класса нужно принять решение о том, будет ли информация храниться в массиве или в связанном списке. Другое решение касается синхрони- зации: может ли к объекту такого класса осуществляться параллель- ный доступ и, если да, следует использовать алгоритм взаимного ис- ключения или алгоритм читателей и писателей. Оба решения отно- сятся только к проектированию класса, не затрагивая его пользовате- лей.
Отделив вопрос о том, что делает класс (спецификация опера- ций), от того, как это делается (проект класса), мы можем изолиро- вать пользователей от модификаций внутреннего устройства класса. Допустимо следующее:
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
240 |
§трансформировать внутренние структуры данных, например применить связанный список вместо массива;
§заменить внутренний механизм синхронизации доступа к дан- ным, в частности использовать алгоритм читателей и писате- лей вместо взаимного исключения.
Описанные изменения влияют только на внутреннее устройство класса: на внутренние структуры данных и внутренние операции, ко- торые имеют доступ к этим структурам.
10.2.2. Операции класса абстрагирования данных. Сохранив внешний интерфейс класса Хранилище Показаний Аналоговых Дат- чиков, рассмотрим два разных метода синхронизации доступа к хра- нилищу:взаимное исключение и алгоритм читателей и писателей.
Наш класс предоставляет две операции (рис.10.3):
читатьАналоговыйДатчик (in идДатчика,
out значениеДатчика, out верхнийПредел, out нижнийПредел, out условиеТревоги)
Эта операция вызывается задачами-читателями, которые хотят получить показания датчиков из хранилища. Она возвращает значе- ние датчика с заданным идентификатором, его верхний и нижний пределы, а также условие тревоги. Если значение попадает в диапа- зон между верхним и нижним пределом, то датчик функционирует нормально. Если же значение оказывается меньше нижнего или боль- ше верхнего предела, то условие тревоги будет равно нижнему или верхнему пределу соответственно.
обновитьАналоговыйДатчик (in идДатчика, in значениеДатчика)
Данная операция вызывается задачами-писателями, которые хо- тят поместить в хранилище новое значение датчика, прочитанное из внешней среды. Операция проверяет, попало ли значение в безопас- ный диапазон, и, если это не так, устанавливает соответствующее значение условияТревоги.
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
241 |
Рис.10.3. Пример параллельного доступа к объекту абстрагирования данных
10.2.3. Синхронизация методом взаимного исключения. Сначала рассмотрим решение, основанное на взаимном исключении. В таком случае используется предоставляемый операционной системой дво- ичный семафор, у которого есть операции acquire (запросить) и release (освободить). Чтобы гарантировать взаимное исключение, каж- дая задача должна вызвать операцию acquire семафора readWriteSemaphore (изначально он установлен в единицу) перед тем, как пы- таться получить доступ к хранилищу. Закончив работу с хранилищем, задача обращается к операции release. Вот псевдокод операций чте- ния и обновления:
class ХранилищеПоказанийАналоговыхДатчиков private readWriteSemaphore : Semaphore := 1 public читатьАналоговыйДатчик (in идДатчика;, out значениеДатчика, out верхнийПредел,
out нижнийПредел, out условиеТревоги) -- Критическая секция операции чтения. acquire (readWriteSemaphore) ;
значениеДатчика := хранилищеПоказаний (идДатчика, значение);
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
242 |
верхнийПредел := хранилищеПоказаний (идДатчика, верх); нижнийПредел := хранилищеПоказаний (идДатчика, низ);
условиеТревоги := хранилищеПоказаний (идДатчика; тревога); release(readWriteSemaphore);
end читатьАналоговыйДатчик;
При выполнении операции обновить надо не только записать в хранилище новое значение датчика, но и проверить условие тревоги:
public обновитьАналоговыйДатчик (in идДатчика, in значениеДатчика)
-- Критическая секция операции записи. acquire (readWriteSemaphore);
хранилищеПоказаний (идДатчика, значение) := значениеДатчика;
if значениеДатчика >= хранилищеПоказаний АналоговыхДатчиков(идДатчика, верх)
then хранилищеПоказаний (идДатчика, тревога) := верх;
elseif значениеДатчика<= хранилищеПоказаний(идДатчика, низ)
then хранилищеПоказаний (идДатчика, тревога) := низ;
else хранилищеПоказаний (идДатчика, тревога) := норма;
end if; release(readWriteSemaphore);
end обновитьАналоговыйДатчик;
10.2.4. Синхронизация нескольких читателей и писателей. При-
менение указанного метода позволяет нескольким читателям одно- временно обращаться к хранилищу, но любой писатель получает мо- нопольный доступ. Для этого применяются два двоичных семафора: readerSemaphore и readWriteSemaphore, инициализированных значе-
нием 1. Кроме того, хранится текущее число Читателей, первона-
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
243 |
чально равное нулю. Семафор readerSemaphore используется читате- лями, чтобы гарантировать взаимно исключающее обновление счет- чика читателей. Семафор readWriteSemaphore задействован писате- лями для обеспечения взаимно исключающего доступа к хранилищу. Но к данному семафору обращаются также и читатели. Он захватыва- ется первым читателем перед началом чтения из хранилища и осво- бождается последним читателем, закончившим чтение. Ниже приве- ден псевдокод операция чтения и обновления:
class ХранилищеПоказанийАналоговыхДатчиков private числоЧитателей : Integer : = 0;
readerSemaphore :. Semaphore := 1; readWriteSemaphore : Semaphore := 1;
public читатьАналоговыйДатчик (in идДатчика, out значениеДатчика, out верхнийПредел, out нижнийПредел, out условиеТревоги)
--Операция чтения вызывается задачами-
--читателями. Доступ к хранилищу разрешен
--одновременно нескольким читателям
--при условии, что нет ни одного писателя. acquire (readerSemaphore) ;
Увеличить числоЧитателей; if числоЧитателей = 1
then acquire (readWriteSemaphpre) ; release (readerSemaphore) ;
значениеДатчика := хранилищеПоказаний (идДатчика, значение); верхнийПредел := хранилищеПоказаний (идДатчика, верх); нижнийПредел := хранилищеПоказаний (идДатчика, низ);
условиеТревоги := хранилищеПоказаний (идДатчика, тревога);
acquire (readerSemaphore) ;
Уменьшить числоЧитателей; if числоЧитателей = 0
then release (readWriteSemaphore); release(readerSemaphore);
end читатьАналоговыйДатчик;
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
244 |
Псевдокод операции обновления аналогичен написанному ранее для алгоритма взаимного исключения, поскольку писатели, желаю- щие обновить хранилище, должны обеспечить взаимно исключаю- щий доступ к нему:
public обновитьАналоговыйДатчик (in идДатчика, in значениеДатчика)
-- Критическая секция операции записи. acquire (readWriteSemaphore) ;
хранилищеПоказаний (идДатчика, значение) := значениеДатчика;
if значениеДатчика >= хранилищеПоказаний (идДатчика, верх)
then хранилищеПоказаний (идДатчика, тревога) := верх;
elseif значениеДатчика <= хранилищеПоказаний (идДатчика,. низ) then хранилищеПоказаний (идДатчика, тревога) := низ;
else хранилищеПоказаний (идДатчика, тревога) := норма;
end if; release(readWriteSemaphore) ;
end обновитьАналоговыйДатчик;
Проблема решена, но код синхронизации оказался переплетен- ным с кодом доступа к хранилищу. Такие обязанности желательно развести, и в следующем разделе мы покажем, как это сделать.
10.2.5. Синхронизация нескольких читателей и писателей с по-
мощью монитора. Ниже речь пойдет о применении мониторов для решения проблемы нескольких читателей и писателей. Напомним, что операции монитора выполняются в условиях взаимного исключе- ния, поэтому представленное выше решение задачи о доступе к хра- нилищу показаний аналоговых датчиков методом взаимного исклю- чения легко реализуется и с помощью мониторов. Однако к задаче
посредством алгоритма читателей и писателей мониторы напрямую применяться не могут, так как операция читатьАналоговый Датчик
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
245 |
должна одновременно выполняться несколькими читателями. Поэто- му мы поступим иначе: инкапсулируем аспекты алгоритма читателей
иписателей, касающиеся синхронизации, в монитор и перепроекти-
руем класс Хранилище Показаний Аналоговых Датчиков. Приведем два решения. Первое реализует ту же функциональность, что и в пре- дыдущем разделе, а второе обладает дополнительными функциями, предотвращающими ущемление писателей.
Объявим монитор ReadWrite, который использует два семафора
ипредоставляет четыре взаимно исключающие операции. Семафоры назовем reader Semaphore и readWriteSemaphore. Четыре вышеупомя- нутые операции – это startRead, endRead, startWrite и endWrite. Зада-
ча-читатель вызывает операцию startRead перед началом чтения и операцию endRead после его окончания. Задача-писатель вызывает операцию startWrite перед началом чтения и операцию endWrite после его окончания. Устройство монитора на базе семафоров описано в разделе 3.8.2. Такой монитор предоставляет для захвата ресурса опе- рацию acquire, которая может приостановить задачу, если ресурс за- нят, а также операцию release для освобождения ресурса.
Операция startRead сначала должна захватить семафор readerSemaphore, увеличить число читателей и освободить семафор. Если счетчик читателей был равен нулю, то startRead должна захватить семафор readWriteSemaphore, который занимает первый читатель, а освобождает последний. Хотя операции монитора выполняются вза- имно исключающим образом, семафор readerSemaphore все же ну- жен. Дело в том, что читатель может быть приостановлен в ожидании семафора readWriteSemaphore, в подобном случае он разблокирует монитор ReadWrite. Если другой читатель в этот момент захватит мо- нитор, вызвав startRead или endRead, он будет ожидать семафора readerSemaphore. Ниже представлен проект монитора ReadWrite:
monitor ReadWrite
--Предназначен для предоставления доступа к
--ресурсам нескольким читателям и одному
--писателю.
--Объявляет целочисленный счетчик числа
--читателей.
--Объявляет семафор для доступа к счетчику
--читателей.
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
246 |
-- Объявляет семафор для взаимно -- исключающего доступа к буферу. private числоЧитателей : Integer = 0;
readerSemaphore : Semaphore; readWriteSemaphore : Semaphore;
public startRead ()
--Читатель вызывает эту операцию перед
--началом чтения. readerSemaphore.acquire; if числоЧитателей = 0
then readWriteSemaphore.acquire;
Увеличить числоЧитателей; readerSemaphore.release;
end startRead; public endRead ()
--Читатель вызывает эту операцию после
--окончания чтения. readerSemaphore.acquire ;
Уменьшить числоЧитателей; if числоЧитателей = 0
then readWriteSemaphore.release; readerSemaphore.release;
end endRead;
public startWrite ()
--Писатель вызывает эту операцию перед -- началом записи. readWriteSemaphore.acquire;
end startWrite; public endWrite ()
--Писатель вызывает эту операцию после
--окончания записи. readWriteSemaphore.release;
end endWrite; end ReadWrite;
Теперь перепроектируем класс Хранилище Показаний Аналого- вых Датчиков так, чтобы он мог воспользоваться монитором ReadWrite. Для этого объявим в нем закрытый экземпляр монитора. Опе- рация читатьАналоговыйДатчик теперь вызывает операцию мони-
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
247 |
тора startRead перед началом чтения из хранилища и операцию endRead после его окончания. Операция обновитьАналоговыйДатчик вызывает операцию монитора startWrite перед началом записи в хра- нилище и операцию endWrite после ее окончания.
class ХранилищеПоказанийАналоговыхДатчиков private multiReadSingleWrite : ReadWrite public читатьАналоговыйДатчик (in идДатчика, out значениеДатчика, out верхнийПредел,
out нижнийПредел, out условиеТревоги) multiReadSingleWrite.startRead();
значениеДатчика : == хранилищеПоказаний (идДатчика, значение);
верхнийПредел := хранилищеПоказаний (идДатчика, верх); нижнийПредел := хранилищеПоказаний
(идДатчика, низ); условиеТревоги := хранилищеПоказаний
(идДатчика, тревога); multiReadSingleWrite.endRead() ;
end читатьАналоговыйДатчик;
public обновитьАналоговыйДатчик (in идДатчика, in значениеДатчика)
-- Критическая секция операции записи. multiReadSingleWrite.startWrite() ;
хранилищеПоказаний (идДатчика, значение) := значениеДатчика;
if значениеДатчика >= хранилищеПоказаний (идДатчика, верх)
then хранилищеПоказаний (идДатчика, тревога) := верх;
elseif значениеДатчика <= хранилищеПоказаний (идДатчика, низ)
then хранилищеПоказаний (идДатчика, тревога) := низ;
else хранилищеПоказаний (идДатчика, тревога) := норма;
end if; multiReadSingleWrite.endWrite();
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
248 |
end обновитьАналоговыйДатчик;
end ХранилищеПоказанийАналоговыхДатчиков;
10.2.6. Синхронизация нескольких читателей и писателей без ущемления писателей. В предыдущем варианте решения есть одно неудобство. Если от читателей постоянно поступают запросы на чте- ние, писателю в течение неопределенно долгого времени может быть отказано в доступе к хранилищу. Этот феномен называется ущемле- нием писателя (writer starvation). Ниже показано решение проблемы путем введения дополнительного семафора writer Waiting. Операция startWrite теперь должна захватить семафор writerWaiting до захвата семафора readWrite Semaphore. Операция startRead захватывает (и ос- вобождает) семафор writerWaiting перед тем, как захватить reader Semaphore.
Поясним, для чего нужны такие изменения. Предположим, что несколько читателей заняты чтением, а писатель в этот момент пыта- ется обновить данные. Он успешно захватывает семафор writerWaiting, но дальше вынужден ждать, пока читатели освободят семафор readWriteSemaphore. Если приходит новый читатель, то он вызывает startRead и приостанавливается, ожидая освобождения семафора writerWaiting. Тем временем уже имеющиеся читатели заканчивают свои операции, и последний освобождает семафор readWriteSemaphore, который тут же переходит в распоряжение ожидающего писа- теля, а тот освобождает семафор writerWaiting, позволяя занять его читателю или писателю. В приведенном ниже псевдокоде реализации операций startRead и startWrite изменены:
monitor ReadWrite
--Предотвращает ущемление писателей за счет
--дополнительного семафора.
--Предназначен для предоставления доступа к
--ресурсам нескольким читателям и одному
--писателю.
--Объявляет целочисленный счетчик числа
--читателей.
--Объявляет семафор для доступа к счетчику
--читателей.
--Объявляет семафор для взаимно
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
249 |
-- исключающего доступа к буферу. -- Объявляет семафор для ожидающих -- писателей.
private числоЧитателей : Integer = 0; readerSemaphore : Semaphore; readWriteSemaphore: Semaphore; writerWaitingSemaphore : Semaphore;
public startRead ()
--Читатель вызывает эту операцию перед
--началом чтения. writerWaitingSemaphore.acquire; writerWaitingSemaphore.release; readerSemaphore.acquire;
if числоЧитателей = 0
then readWriteSemaphore.acquire;
Увеличить числоЧитателей; readerSemaphore.release;
end startRead; public endRead ()
--Читатель вызывает эту операцию после
--окончания чтения. readerSemaphore.acqui.re;
Уменьшить числоЧитателей; if числоЧитателей = 0
then readWriteSemaphore.release;
readerSemaphore.release; end endRead;
public startWrite ()
--Писатель вызывает эту операцию перед
--началом записи. writerWaitingSemaphore.acquire; readWriteSemaphore.acquire; writerWaitingSemaphore.release;
end startWrite; public endWrite ()
--Писатель вызывает эту операцию после
--окончания записи. readWriteSemaphore.release;
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
250 |
end endWrite; end ReadWrite;
Класс Хранилище Показаний Аналоговых Датчиков может пользоваться всеми преимуществами нового решения, хотя мы не из- менили в нем ни одной строчки.
10.3. Проектирование разъемов для межзадачных коммуникаций
Классы-разъемы инкапсулируют детали межзадачных коммуни- каций, например сильно и слабо связанный обмен сообщениями.
Сервисы для межзадачных коммуникаций и синхронизации может предоставлять многозадачное ядро. Подобные механизмы есть также в некоторых языках параллельного программирования, в частности Ada или Java. Но ни один из этих языков не поддерживает слабо свя- занный обмен сообщениями. Чтобы реализовать указанную возмож- ность, необходимо спроектировать скрывающий информацию класс MessageQueue, инкапсулирующий очередь сообщений и предостав- ляющий операции для доступа к ней. Классы такого вида называются
разъемами.
Ниже будут описаны три класса-разъема для реализации слабо связанного обмена сообщениями, сильно связанного обмена без отве- та и сильно связанного обмена с ответом. Каждый разъем представ- ляет собой монитор, одновременно обеспечивающий синхронизацию и скрывающий информацию о том, как это делается. В разъемах при- меняется синхронизация по условию. Такие мониторы могут исполь-
зоваться как в однопроцессорной так и в многопроцессорной системе
сразделяемой памятью.
10.3.1.Проектирование разъема, реализующего очередь сооб-
щений. Разъем, реализующий очередь сообщений, используется для инкапсуляции механизма слабо связанного обмена сообщениями. Это монитор, инкапсулирующий очередь, которая обычно существует в виде связанного списка. Разъем предоставляет синхронизированные операции send для отправки сообщения (вызывается задачей- производителем) и receive для получения сообщения (вызывается за- дачей-получателем) – рис.10.4. Производитель приостанавливается, если очередь заполнена (messageCount = maxCount) и возобновляет работу, когда освобождается место для размещения нового сообще-
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
251 |
ния. Поместив сообщение в очередь, производитель продолжает ра- ботать и в состоянии посылать новые сообщения. Потребитель при- останавливается, когда очередь пуста (messageCount = 0) и ак- тивизируется, как только в очередь поступит сообщение. Потреби- тель не приостанавливается, если в очереди есть сообщения. Предпо- лагается, что может быть несколько производителей и один потреби- тель.
Рис. 10.4. Пример разъема для реализации очереди сообщений
monitor MessageQueue
--Инкапсулирует очередь сообщений,
--рассчитанную максимум на maxCount
--сообщений. Операции монитора выполняются
--взаимно исключающим образом.
private maxCount : Integer; private messageCount : Integer = 0; public send (in message)
while messageCount = maxCount do wait;
Поместить сообщение в очередь;
Увеличить messageCount;
if messageCount = 1 then signal; end send;
public receive (out message) while messageCount = 0 do wait;
Извлечь сообщение из очереди;
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
252 |
Уменьшить messageCount;
if messageCount = maxCount - 1 then signal; end receive;
end MessageQueue;
10.3.2. Проектирование разъема, реализующего буфер сообще-
ний. Разъем, реализующий буфер сообщений, используется для ин-
капсуляции механизма сильно связанного обмена сообщениями без ответа. Это монитор, инкапсулирующий буфер на одно сообщение.
Разъем предоставляет синхронизированные операции для отправки и получения сообщений (рис. 10.5). Производитель вызывает операцию send, а потребитель – операцию receive. Производитель приостанав- ливается, если буфер заполнен. Поместив сообщение в буфер, произ- водитель ждет, пока потребитель примет его. Потребитель приоста- навливается, когда буфер пуст. Предполагается, что может быть не- сколько производителей и один потребитель.
monitor MessageBuffer
--Инкапсулирует буфер сообщений, в котором
--может находиться не более одного
--сообщения. Операции монитора выполняются
--взаимно исключающим образом.
private messageBufferFull : Boolean = false; private messageCount : Integer = 0;
public send (in message)
Поместить сообщение в буфер; messageBufferFull = true; signal;
while messageBufferFull = true do wait; end send;
public receive (out message)
while messageBufferFull = false do wait;
Извлечь сообщение из буфера; messageBufferFull = false; signal;
end receive;
end MessageBuffer;
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
253 |
Рис. 10.5. Пример разъема для реализации буфера сообщений
10.3.3. Проектирование разъема, реализующего буфер сообще-
ний с ответом. Разъем, реализующий буфер сообщений с ответом,
используется для инкапсуляции механизма сильно связанного обмена сообщениями с ответом. Это монитор, инкапсулирующий буфер на одно сообщение и буфер на один ответ. Разъем предоставляет син- хронизированные операции для отправки и получения сообщений, а также для отправки ответа (рис.10.6). Производитель вызывает опе- рацию send для пересылки сообщения, а потребитель – операцию receive для приема сообщения и операцию reply для отправки ответа. Поместив сообщение в буфер, производитель ждет ответа от потре- бителя. Потребитель приостанавливается, когда буфер пуст. Предпо- лагается, что может быть несколько производителей и один потреби- тель.
monitor MessageBuffer&Response
--Инкапсулирует буфер сообщений, в котором
--может находиться не более одного
--сообщения, и буфер, в котором может
--находиться не более одного ответа.
--Операции монитора выполняются взаимно
--исключающим образом.
private messageBufferFull : Boolean = false; private responseBufferFull : Boolean = false; private messageCount : Integer = 0;
public send (in message)
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
254 |
Поместить сообщение в буфер; messageBufferFull = true; signal ;
while responseBufferFull = false do wait;
Извлечь ответ из буфера; responseBufferFull = false;
end send;
public receive (out message)
while messageBufferFull = false do wait;
Извлечь сообщение из буфера; messageBufferFull = false;
end receive;
public reply (in response)
Поместить ответ в буфер; responseBufferFull = true; signal ;
end reply;
end MessageBuffer&Response
Рис.10.6. Пример разъема для реализации буфера сообщений с ответом
10.3.4. Проектирование кооперативных задач с использованием разъемов. Теперь рассмотрим проектирование группы кооперативных задач, общающихся между собой с помощью объектов-разъемов. Для иллюстрации воспользуемся примером из подсистемы Банкомат.
www.pdffactory.com
СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИ |
255 |
Разъемы для этой подсистемы изображены на рис.10.7; есть два разъ- ема – очереди сообщений и один разъем – буфер сообщений.
Объект Очередь Сообщений Управления Банкоматом инкапсу-
лирует очередь входных сообщений задачи Контроллер Банкомата, для которой есть несколько производителей. Объект Очередь Сооб- щений Приглашений инкапсулирует очередь сообщений, посылаемых задачей Контроллер Банкомата задаче Интерфейс Клиента. И в том, и в другом случае производитель вызывает операцию send объ- екта-разъема, а потребитель – операцию receive того же объекта.
Имеется также разъем буфер Сообщений Устройства Считывания,
который инкапсулирует синхронный обмен без ответа между задача-
ми Контроллер Банкомата и Интерфейс Устройства Считывания Карточек.
Наконец, есть объект заместитель Банковского Сервера. Он скрывает детали коммуникации с удаленным Банковским Сервером, применяя синхронный обмен сообщениями без ответа. Например, в языке Java этот заместитель воспользовался бы механизмом вызова удаленных методов (RMI), описанным ранее.
Рис.10.7. Пример кооперативных задач, использующих разъемы
www.pdffactory.com