While true do while true do
Begin begin
(* чтение новых данных *) wait(data_available);
signal(data_available); (*обработка данных *)
end; end;
Это решение отделяет операцию ввода данных от их обработки. На появление новых данных указывает значение семафора, отличное от 0. Если существует механизм буферизации (промежуточного хранения) новых данных, то процедура обработки сможет получить все данные, даже если они поступают быстрее, чем она в состоянии их принять. В системах реального времени принято отделять процедуры, требующие быстрой реакции, например прием данных с внешнего порта, от других процессов.
Для защиты критических секций, в которые по определению в любой момент времени может входить только один процесс, используются двоичные семафоры, также называемые mutex(от mutual exclusion - взаимное исключение). В этом случае нельзя использовать обычные семафоры, так как их значение может превышать 1 и, следовательно, несколько программ могут получить доступ к ресурсу, уменьшая значения семафора. Операция signalнад двоичным семафором всегда устанавливает его значение в 1. Операция waitуменьшает это значение с 1 до 0 и разрешает процессу продолжаться дальше. Если семафор имеет значение 0, то процесс, выполняющий wait, должен ждать до тех пор, пока значение семафора не изменится.
Ошибки синхронизации, связанные с неправильным использованием семафоров, трудно выявляются. Процесс, не выполняющий операцию wait, может войти в критическую секцию одновременно с другим процессом, что приведет к непредсказуемым результатам. Естественно, нельзя говорить, что такая ошибка выявится при тестировании; она даже может никогда не произойти за все время существования системы. Легче найти противоположную ошибку - отсутствующая операция signalможет в определенный момент привести к остановке, по крайней мере, одного из процессов, что достаточно просто обнаружить.
Компилятор не имеет возможности проверить, правильно ли используются семафоры, то есть, согласованы ли операции waitс операциями signalв других модулях и связаны ли семафоры с соответствующими ресурсами, поскольку это зависит от логики алгоритма. Более того, размещение семафоров в программе, как и других команд, произвольно. Забота о проверке правильности программы лежит на программисте. Использование структурного программирования существенно облегчает решение этой задачи.
Семафоры являются удобным средством высокого уровня для замещения операции test_and_setи помогают избежать циклов занятого ожидания. Однако их неправильное использование может привести к ситуации гонок и к тупикам.
4. События
В некоторых случаях несколько процессов, имеющих доступ к общим данным, должны работать с ними только при выполнении некоторых условий, необязательно связанных с данными и разных для каждого процесса. Условием, например, может быть поступление новых данных на входной порт. Все процессы имеют следующую структуру
Begin
wait untilcondition;
Modifydata; end
Программа делится на две основные части. Сначала проверяются условия, а затем производятся операции над данными. Процедура проверки условия не изменяет данных и поэтому не требует какой-либо специальной защиты доступа. Однако доступ к данным для модификации должен быть координирован между процессами.
Если использовать семафоры, то их потребуется два: один - для контроля доступа в защищенную область с данными, а другой - для индикации изменения общих данных и, соответственно, необходимости повторной проверки условий.
Применение первого семафора просто, а для второго необходимо следить за числом ожидающих процессов и обеспечить, что при изменении условия ожидающие процессы будут активизированы с целью его проверки, то есть генерацию сигналов семафора, число которых равно числу ожидающих процессов. Это решение неудовлетворительно из-за большого расхода машинного времени на многочисленные проверки, при этом в программе довольно легко ошибиться.
Для решения этой проблемы была введена новая переменная синхронизации event(событие), с которой связаны операции await(ждать) и cause(вызвать). Процесс, выполнивший операцию await(event), остается в состоянии ожидания, пока значение переменной event не изменится. Это изменение контролируется с помощью операции cause. При наступлении события, то есть выполнении операции cause(event), освобождаются все ожидающие его процессы, в то время как в случае семафора освобождается лишь один процесс. Операции с событиями можно реализовать либо с помощью двоичной переменной, либо с помощью счетчика, при этом основные принципы остаются одинаковыми.
Глагол to await имеет значение не только "ждать", но и "предстоять", то есть конструкцию await (А) можно трактовать, как "предстоит событие А". Глагол to cause означает "быть причиной", побудительным мотивом, "вызвать что-либо". Конструкция cause (А) интерпретируется как "вызвать событие А" (в литературе и в операционных системах иногда используются и другие названия).
В противоположность семафору, переменную события нельзя использовать для защиты ресурса от конкурирующего доступа нескольких процессов, поскольку по определению она освобождает все ожидающие процессы. Вышеприведенная проблема решается с помощью переменной события и семафора, если все программы имеют следующий вид
varmutex: semaphore; change: event;
Begin
while notcondition do await(change); wait(mutex);
(* обработка общих переменных *) signal(mutex); cause(change);
end;
При каждом изменении переменной event все процессы проверяют condition, и только те из них, для которых condition выполнено, могут продолжаться. Доступ к общему ресурсу защищен с помощью семафора mutex, при этом продолжается только один процесс. Это решение проще, чем основанное только на семафорах. Оно также более эффективно, поскольку процессы проверяют условия только тогда, когда это имеет смысл, т.е. после изменения значения соответствующих переменных.
Важный тип события в системах реального времени связан с внешними прерываниями. Программа обработки - обработчик прерываний - ждет прерывания. Когда оно происходит, исполнение обработчика возобновляется.
Лекция 3.3. Механизмы защиты ресурсов
1. Взаимные исключения.
2. Предотвращение тупиков.
3. Синхронизирующие объекты операционных систем.
4. Сигналы.
1. Взаимные исключения
Запрет прерываний может носить только исключительный характер. Другой подход к защите ресурсов основан на взаимном исключении (mutual exclusion). Никакой процесс не может получить доступ к ресурсу, пока этот ресурс не будет явно освобожден процессом, который захватил его первым.
Корректная защита ресурсов предполагает следующее:
1. В любой момент времени доступ к защищенному ресурсу имеет только один процесс.
2. Процессы остаются взаимно независимыми. Остановка одного из процессов не должна препятствовать продолжению других.
Сформулированные требования соответствуют двум характеристикам -безопасности и живучести. Безопасность (safety) означает, что доступ к защищенному ресурсу в любой момент времени возможен только со стороны одного из процессов. Живучесть (liveness) означает, что программа когда-нибудь обязательно будет выполнена, иными словами, что она не остановится, и не будет ждать бесконечно. Безопасность - это статическое свойство, а живучесть - динамическое. Безопасности можно добиться за счет частичного или полного отказа от параллельного исполнения процессов. В действительности наиболее надежными являются строго последовательные программы, поскольку в этом случае вообще невозможен параллельный доступ к ресурсу из различных частей программы.
Распространенный метод управления доступом к ресурсам - применение переменных защиты. Простейший метод защиты основан на одной двоичной переменной f1. Эта переменная изменяется обоими процессами таким образом, что один из них имеет доступ к защищенному ресурсу, когда f1 = true, а другой - когда f1 = false.
program protect_example (* защита ресурса *)
var fl: boolean;
begin
f1 : = true;
cobegin
while true do (* бесконечный цикл *)
begin (* процесс А *)
repeat until f1 = true;
(* защищенный ресурс *)
f1 := false;
…
end; (* процесс А *)
while true do (* бесконечный цикл *)
begin (* процесс В *) repeat until f 1 = false;
(* защищенный ресурс *)
f1: = true;
…
end; (* процесс В *)
coend;
end (* protect_example *)
Это решение удовлетворяет принципу взаимного исключения - два процесса проверяют переменную f1 и входят в критическую секцию только тогда, когда f1 имеет разные значения. Процесс, находящийся в критической секции, может считать, что он владеет ресурсом монопольно.
С другой стороны, это решение создает новые проблемы. Наиболее медленный процесс определяет общую скорость исполнения. Не имеет значения, является ли А быстрее, чем В или наоборот, поскольку каждый процесс для своего развития должен ждать, когда другой изменит значение f1. Кроме этого, если исполнение процесса по той или иной причине будет приостановлено, второй тоже должен быть остановлен, даже после одного цикла. Более того, циклы занятого ожидания (busy loop), в которых проверяется переменная защиты, напрасно расходуют процессорное время.
Эти проблемы - следствие введения управляющей переменной f1, которая для синхронизации доступа к ресурсу создает дополнительные связи между процессами. Модули, которые должны быть в принципе независимыми, связаны через f1, которая делает из двух модулей фактически последовательный процесс. Тот же результат можно получить, исключив f1 и выполняя оба процесса последовательно в одном цикле.
Другое решение — переустанавливать защитную переменную f1 после проверки ее значения и перед доступом к защищенному ресурсу т.е. все процессы должны иметь следующий вид
repeat until f1 = true;
f1 := false;
(* защищенный ресурс *)
f1 := true;
…
В этом случае процессы не связаны, и условие живучести выполнено, но решение не является корректным. Если прерывание для переключения процесса останавливает процесс А после контроля f1 = true, но перед присваиванием f1 = false, а процесс В производит аналогичную проверку f1, то оба процесса получают доступ к защищенному ресурсу, что противоречит требованию безопасности. Использование для защиты ресурса только одной переменной приводит к необходимости защищать переменную, поскольку она сама становится общим ресурсом.
Было предложено несколько решений, основанных на нескольких переменных защиты, но они скорее могут считаться курьезами, имеющими мало практического значения. В заключение отметим, что для синхронизации параллельных процессов лучше не вводить новых переменных, поскольку они добавляют новые связи и сами становятся общими ресурсами.
Чтобы обойти эту проблему, некоторые процессоры имеют команду test_and_set ("проверить_и_установить"), выполняющую проверку значения булевой переменной и ее переустановку в ходе одной операции, которую нельзя прервать. Смысл команды test_and_set в том, что на ее базе можно построить процедуры синхронизации и защиты ресурсов. Объединения в одной операции проверки переменной и ее модификации достаточно для обеспечения защиты.
Команда test_and_set функционально эквивалентна циклу read-modify-write на шине VMEbus. В обоих случаях гарантируется неразрывность двух операций - чтения и записи. Если команда test_and_set отсутствует в используемом языке программирования или в наборе команд процессора, то ее можно смоделировать другими средствами при условии, что допустим запрет прерываний на короткое время.
Реализация критических секций и взаимного исключения в распределенной системе сама по себе представляет проблему. Для начала, нет прямого эквивалента команды test_and_set, поскольку в этом случае имеется более одного процессора. В принципе, для каждого ресурса можно установить единого координатора. Любой процесс, желающий получить доступ к ресурсу, сначала запрашивает координатора, который дает разрешение только одному из запрашивающих процессов. Однако это решение не является столь простым, как кажется. Единый координатор процессов является узким местом - и при его отказе ресурс остается либо заблокированным, либо незащищенным. Более того, если ресурс является просто переменной в памяти, то строить целый алгоритм для его защиты нерационально. На самом деле координатор сам является ресурсом, за доступ к которому будет происходить конкуренция, не говоря уже о том, что в распределенной системе для посылки запроса нужно еще получить и доступ к каналу связи.
Возможной альтернативой является использование маркера, который перемещается между процессами. При этом в критическую секцию может войти только владелец маркера. Здесь возникают те же проблемы, что и в сетях: в случае сбоя в процессе, являющемся владельцем маркера, должен существовать механизм регенерации маркера. Поэтому для защиты небольшого числа переменных в памяти этот метод может оказаться громоздким и трудно реализуемым.
В заключение отметим, что в распределенных системах не существует практичного, эффективного и простого метода защиты ресурсов, сравнимого с командой test_and_set в однопроцессорных конфигурациях. Каждый случай необходимо оценивать индивидуально и выбирать соответствующее практическое решение.
2. Предотвращение тупиков
Рассмотрим ситуацию, в которой два или больше процессов в системе приостановлены и ожидают каких-нибудь событий. Если такие события для каждого из ожидающих процессов могут быть инициированы только другим ожидающим процессом, то все процессы окажутся в состоянии бесконечного ожидания. Такая ситуация называется тупиком (deadlock) (рис. 1).
Похожая ситуация возникает, когда один или несколько процессов продолжают исполняться фактически на одном месте. Это называется зависанием (starvation). Например, если процесс непрерывно проверяет значение условной переменной, которое не изменяется, поскольку все остальные процессы также заняты проверкой. Иными словами, процессы, оказавшиеся в тупике, находятся в очереди ожидания (т. е. они блокированы), а зависшие процессы исполняются, но фактически на одном месте.
Рисунок 1. - Тупик: а – взаимный; б – циркулярный
Тупик и одновременный доступ к защищенному ресурсу являются двумя симметричными проблемами, относящимися к чрезвычайным ситуациям. В одном случае каждый процесс ждет других процессов, во втором -несколько процессов выполняются параллельно.
Можно предложить несколько подходов к решению проблемы тупиков. Простейшим из них является полное игнорирование проблемы и работа в режиме, когда при возникновении тупика некоторые процессы уничтожаются, например оператором, или производится ручная перезагрузка системы. Естественно, такое решение неприемлемо для систем реального времени, в особенности, если они должны работать без участия оператора.
Кроме стратегии с привлечением оператора, существуют еще и другие -автоматического обнаружения и предотвращения. Первая предполагает перераспределение ресурсов для разрешения ситуации или, в крайнем случае, уничтожение одного из процессов. Вторая - распределение ресурсов так, что тупики не возникают вообще.
Для обнаружения тупиковой ситуации необходимо непрерывно проверять состояние всех исполняющихся процессов и их взаимодействие для обнаружения циклов типа показанных на рис. 1. Такой контроль можно делать с помощью фоновой (background) программы, периодически запускаемой планировщиком. Однако и такая программа не может гарантированно выявить все тупиковые ситуации. В распределенных системах информация о состоянии всех процессов на всех ЭВМ также должна поступать к программе обнаружения тупиковых ситуаций. Помимо повышенной нагрузки на сеть, которая при этом возникает, имеется риск несогласованности сообщений о состоянии процессов, в результате которого может произойти ошибочное выявление тупиковой ситуации с последующим уничтожением соответствующих процессов.
Предотвращение означает попытку вообще избежать ситуаций, которые могут привести к тупику. Программы должны быть структурированы и взаимодействие процессов должно быть организовано таким образом, чтобы тупиковые ситуации были исключены вообще.
Для возникновения тупика должны выполниться одновременно несколько условий. Если хотя бы одно из них не выполнено, тупик не может возникнуть.
1. Взаимное исключение. Существуют системные ресурсы, к которым разрешен монопольный доступ.
2. Невытесняющее распределение ресурсов. Ресурс может быть освобожден только тем процессом, который его захватил, или, иначе говоря, ресурс не может быть освобожден извне захватившего его процесса.
3. Последовательный захват ресурсов. Процесс запрашивает ресурсы по одному, т. е. по мере необходимости.
4. Захват ресурсов в обратном порядке.
Эти четыре утверждения косвенно дают ключ к предотвращению тупиковых ситуаций. Достаточно, чтобы одно из них не выполнялось, и тупик не возникнет.
Первое утверждение выполняется всегда, так как взаимное исключение является принципиальным для гарантии упорядоченного управления общими ресурсами.
Второе утверждение требует, чтобы операционная система распознавала тупиковые ситуации и реагировала соответственно, вынуждая процесс освободить ресурс. Это решение приемлемо лишь в случае, если допускается принудительное уничтожение процесса, и зависит от механизма восстановления.
В соответствии с третьим утверждением альтернативой выделению по одному является выделение всех необходимых ресурсов одновременно. Практичность этого решения, естественно, зависит от вида этих ресурсов и от того, могут ли без них обойтись другие процессы, пока не завершится захвативший их процесс. Если процессу выделяется десяток переменных на время выполнения небольшого количества команд, без информации о том, какие из них будут действительно использоваться — это одна ситуация, а если один процесс надолго блокирует доступ к целой базе данных — это совсем другое дело.
Если система структурирована в соответствии с моделью "клиент-сервер" и работает на основе замкнутых транзакций, то проблему тупиков решить проще. В случае возникновения тупика можно просто отменить транзакцию, а не уничтожать один или несколько процессов.
Нарушение четвертого запрета чаще всего приводит к тупикам. Если двум процессам требуются ресурсы А и В и первый их запрашивает в порядке А - В, а второй - В - А, то для возникновения тупика достаточно того, чтобы первый процесс был прерван после захвата ресурса А и управление было передано второму, который, в свою очередь, захватывает ресурс В. После этого каждый процесс будет бесконечно ждать, пока другой не освободит захваченный ресурс.
Четвертое утверждение дает практический способ избежать тупиков. Тупик можно предотвратить, если определен точный порядок (последовательность) запроса ресурсов, соблюдаемый всеми процессами. В приведенном примере это означает, что "А должен быть распределен перед В" и что все процессы строго следуют этому правилу. При этом освобождение ресурсов должно происходить в порядке, обратном их выделению. Этот метод, в принципе, несложно применить при разработке системы реального времени, пока процессы находятся в руках одного или небольшой группы программистов, но его практическая ценность быстро уменьшается при возрастающем числе ресурсов или разделяемых переменных.
4. Сигналы
Сигналдает возможность задаче реагировать на событие, источником ко торого может быть операционная система или другая задача. Сигналы вызывают прерывание задачи и выполнение заранее предусмотренных действий. Сигналы могут вырабатываться синхронно, то есть как результат работы самого процесса, а могут быть направлены процессу другим процессом, то есть вырабатываться асинхронно. Синхронные сигналы чаще всего приходят от системы прерываний процессора и свидетельствуют о действиях процесса, блокируемых аппаратурой, например деление на нуль, ошибка адресации, нарушение защиты памяти и т. д.
Примером асинхронного сигнала является сигнал с терминала. Во многи ОС предусматривается оперативное снятие процесса с выполнения. Для этого пользователь может нажать некоторую комбинацию клавиш (Сtгl+С, Сtг1+Вгеаk) в результате чего ОС вырабатывает сигнал и направляет его активному процессу. Сигнал может поступить в любой момент выполнения процесса (то есть он является асинхронным), требуя от процесса немедленного завершения работы. В данном случае реакцией на сигнал является безусловное завершение процесса
В системе может быть определен набор сигналов. Программный код процесса, которому поступил сигнал, может либо проигнорировать его, либо прореагировать на него стандартным действием (например, завершиться), либо выполнить специфические действия, определенные прикладным программистом. В последнем случае в программном коде необходимо предусмотреть специальные системные вызовы, с помощью которых операционная система информируется, какую процедуру надо выполнить в ответ на поступление того или иного сигнала.
Сигналы обеспечивают логическую связь между процессами, а также между процессами и пользователями (терминалами). Поскольку посылка сигнала предусматривает знание идентификатора процесса, то взаимодействие посредством сигналов возможно только между родственными процессами, которые могут получить данные об идентификаторах друг друга.
В распределенных системах, состоящих из нескольких процессоров, каждый из которых имеет собственную оперативную память, блокирующие переменные, семафоры, сигналы и другие аналогичные средства, основанные на разделяемой памяти, оказываются непригодными. В таких системах синхронизация может быть реализована только посредством обмена сообщениями.
Лекция 3.4. Обмен информацией между процессами
1. Общие области памяти.
2. Почтовые ящики.
3. Каналы.
4. Удаленный вызов процедур.
5. Сравнение методов синхронизации и обмена данными.
1. Общие области памяти
Взаимодействующие процессы нуждаются в обмене информацией. Поэтому многозадачная операционная система должна обеспечивать необходимые для этого средства. Обмен данными должен быть прозрачным для процессов, т.е. передаваемые данные не должны изменяться, а сама процедура должна быть легко доступна для каждого процесса.
Простейший метод - использование общих областей памяти, к которым разные процессы имеют доступ для чтения/записи. Очевидно, что такая область представляет собой разделяемый ресурс, доступ к которому должен быть защищен, например, семафором. Главное преимущество общих областей памяти заключается в том, что к ним можно организовать прямой и мгновенный доступ, например один процесс может последовательно записывать поля, а другой затем считывать целые блоки данных.
При программировании на машинном уровне общие области размещаются в оперативной памяти по известным адресам. В языках высокого уровня вместо этого используются глобальные переменные, доступные нескольким дочерним процессам. Так, например, происходит при порождении потоков, для которых переменные родительского процесса являются глобальными и работают как общие области памяти. В случае возможных конфликтов доступа к общим областям они должны быть защищены семафорами.
2. Почтовые ящики
Другой метод, позволяющий одновременно осуществлять обмен данными и синхронизацию процессов, - это почтовые ящики. Почтовый ящик представляет собой структуру данных, предназначенную для приема и хранения сообщений (рис. 1). Для обмена сообщениями различного типа можно определить несколько почтовых ящиков.
Рисунок 1. - Работа почтового ящика
Во многих операционных системах почтовые ящики реализованы в виде логических файлов, доступ к которым аналогичен доступу к физическим файлам. С почтовыми ящиками разрешены следующие операции: создание, открытие, запись/чтение сообщения, закрытие, удаление. В некоторых системах поддерживаются дополнительные служебные функции, например счетчик сообщений в почтовом ящике или чтение сообщения без удаления его из ящика.
Почтовые ящики размещаются в оперативной памяти или на диске и существуют лишь до выключения питания или перезагрузки. Если они физически расположены на диске, то считаются временными файлами, уничтожаемыми после выключения системы. Почтовые ящики не имеют имен подобно реальным файлам - при создании им присваиваются логические идентификаторы, которые используются процессами при обращении.
Для создания почтового ящика операционная система определяет указатели на область памяти для операций чтения/записи и соответствующие переменные для защиты доступа. Основными методами реализации являются либо буфер, размер которого задается при создании ящика, либо связанный список, который, в принципе, не накладывает никаких ограничений на число сообщений в почтовом ящике.
В наиболее распространенных реализациях процесс, посылающий сообщение, записывает его в почтовый ящик с помощью оператора, похожего на оператор записи в файл
put_mailbox ( # 1, message)
Аналогично, для получения сообщения процесс считывает его из почтового ящика с помощью оператора вида
get _mailbox (# 1, message)
Запись сообщения в почтовый ящик означает, что оно просто копируется в указанный почтовый ящик. Может случиться, что в почтовом ящике не хватает места для хранения нового сообщения, то есть почтовый ящик либо слишком мал, либо хранящиеся в нем сообщения еще не прочитаны.
При чтении из почтового ящика самое старое сообщение пересылается в принимающую структуру данных и удаляется из ящика. Почтовый ящик -это пример классической очереди, организованной по принципу FIFO. Операция чтения из пустого ящика приводит к различным результатам в зависимости от способа реализации — либо возвращается пустая строка (нулевой длины), либо операция чтения блокируется до получения сообщения. В последнем случае, чтобы избежать нежелательной остановки процесса, необходимо предварительно проверить число сообщений, имеющихся в данный момент в ящике.
3. Каналы
Канал (pipe) представляет собой средство обмена данными между двумя процессами, из которых один записывает, а другой считывает символы. Этот механизм был первоначально разработан для среды UNIX как средство перенаправления входа и выхода процесса. В ОС UNIX физические устройства ввода/вывода рассматривают как файлы, а каждая программа имеет стандартное устройство ввода (вход) и стандартное устройство вывода (выход), клавиатуру и экран монитора - можно переопределить, например, с помощью файлов. Когда выход одной программы перенаправляется на вход другой, создается механизм, называемый каналом (в операционных системах для обозначения канала используется символ "|"). Каналы применяются в операционных системах UNIX, OS/9 и Windows NT в качестве средства связи между процессами (программами).
Каналы можно рассматривать как частный случай почтового ящика. Различие между ними заключается в организации потока данных - почтовые ящики работают с сообщениями, то есть данными, для которых известны формат и длина, а каналы принципиально ориентированы на неструктурированные потоки символов. В некоторых операционных системах, однако, возможно определить структуру передаваемых по каналу данных. Обычно процесс, выполняющий операцию чтения из канала, ждет, пока в нем не появятся данные. В настоящее время операционные системы включают методы, позволяющие избежать блокировки программы, если это нежелательно с точки зрения ее логики.
Операции над каналами эквивалентны чтению/записи физических файлов. Они включают функции, как определить, открыть, читать, записать, закрыть, удалить. Дополнительные операции могут устанавливать флаги режима доступа, определять размер буфера и т.д.
Благодаря тому, что ввод/вывод в файл и на физические устройства и вход/выход процессов трактуются одинаково, каналы являются естественным средством взаимодействия между процессами в системах "клиент-сервер". Механизм каналов в UNIX может в некоторых случаях зависеть от протокола TCP/IP, а в Windows NT каналы работают с любым транспортным протоколом. Следует иметь в виду, что внешне простой механизм каналов может требовать больших накладных расходов при реализации, особенно в сетевых системах.
4. Удаленный вызов процедур
Модель "клиент-сервер" построена на обмене сообщениями "регулярной" структуры, которые можно передавать, например, через механизм каналов.
Однако основной процедурой обмена данными и синхронизации в среде "клиент-сервер" является удаленный вызов процедур (Remote Procedure Call - RPC). Последний может рассматриваться как вызов подпрограммы, при котором операционная система отвечает за маршрутизацию и доставку вызова к узлу, где находится эта подпрограмма. Нотация обращения к процедуре не зависит от того, является ли она локальной или удаленной по отношению к вызывающей программе. Это существенно облегчает программирование.
В системе реального времени существенно, является RPC блокирующим или нет. Блокирующий RPC не возвращает управление вызывающему процессу, пока не закончит свою работу, например, пока не подготовит данные для ответа. Неблокирующие RPC возвращают управление вызывающей процедуре по истечении некоторого времени (time out) независимо от того, завершила ли работу вызываемая процедура; в любом случае вызывающая программа получает код, идентифицирующий результат выполнения вызова, - код возврата. Таким образом, неблокирующие RPC имеют важное значение, с точки зрения гарантии живучести системы.
5. Сравнение методов синхронизации и обмена данными Может показаться, что основные задачи, связанные с параллельным программированием, взаимным исключением, синхронизацией и коммуникациями между процессами, имеют мало общего, но, в сути - это просто разные способы достижения одной цели. Методы синхронизации можно использовать для организации взаимного исключения и коммуникаций. Аналогично, с помощью техники коммуникаций между процессами можно реализовать функции синхронизации и взаимного исключения процессов.
Например, семафор эквивалентен почтовому ящику, в котором накапливаются сообщения нулевой длины, - операции signal и wait эквивалентны операциям put и get почтового ящика, а текущее значение семафора эквивалентно числу помещенных в почтовый ящик сообщений. Аналогично можно организовать взаимное исключение и защиту ресурсов с помощью почтовых ящиков. В этом случае сообщение выполняет функцию "маркера". Процесс, получивший этот "маркер", приобретает право входить в критическую секцию или распоряжаться ресурсами системы. При выходе из секции или освобождении ресурса процесс помещает "маркер" в почтовый ящик. Следующий процесс читает из почтового ящика, получает "маркер" и может войти в критическую секцию.
Связь между разными подходами имеет практическое значение в том случае, если в системе применяется только один из них, а все остальные нужно строить на его основе. Современные операционные системы, поддерживающие многозадачный режим и операции в реальном времени, применяют все упомянутые методы. Передача сообщений и доступ к общим областям памяти медленнее, чем проверка и обновление семафора и переменной события, и требует дополнительных накладных расходов. Если есть выбор между различными методами синхронизации и взаимодействия, следует использовать тот из них, который лучше решает конкретную проблему - результирующая программа будет понятнее и, возможно, быстрее работать. Кроме того, весьма важно оценить, насколько эффективно в имеющейся программной среде реализуются конкретные решения. Следует избегать незнакомых и неестественных конструкций.
В распределенных системах всегда существует риск потерять сообщение в сети. Если сетевая система сконфигурирована так, что она контролирует правильность передачи сообщения, и имеются средства для повторной передачи утраченных сообщений, то прикладная программа не должна осуществлять дополнительные проверки. Обычно нижний уровень операционной системы и процедуры сетевого интерфейса передают на более высокий уровень код возврата, который прикладная программа должна проверить, чтобы убедиться, была ли попытка успешной или нет, и при необходимости повторить ее.
Если контроль не предусмотрен, например, используется служба IP без транспортного протокола TCP, то прикладная программа несет ответственность за проверку результата передачи. Эта операция сложнее, чем это кажется. Можно использовать сообщение, подтверждающее прием, но нет гарантии, что оно само, в свою очередь, не будет потеряно и отправитель не начнет новую передачу. Эта проблема не имеет общего решения - стратегии передачи сообщений должны в каждом случае рассматриваться индивидуально. Возможным решением является помечать и нумеровать каждое сообщение таким образом, чтобы отправитель и получатель могли следить за порядком передачи. Этот метод используется в некоторых типах коммуникационных протоколов.
Лекция. 3.5. Операционные системы реального времени для интеллектуальных информационных систем
1. Обзор основных направлений развития операционных систем реального времени.
2. Операционная система Spox.
3. Операционная система Multiprox.
4. Операционная система VCOS.
5. Операционная система DEASY.
6. Операционная система UNIX.
7. Операционная система OSF/1 и DСЕ.
8. Операционная система VAX/VMS.
1. Обзор основных направлений развития операционных систем реального времени
Операционные системы реального времени (ОСРВ) используются в тех случаях, когда работоспособность обслуживаемой ими цифровой системы определяется не только результатом обработки поступившей информации, но и длительностью времени получения результата. Области практического применения ОСРВ очень широки. Это системы автоматизации производства, контрольно-измерительные системы, телекоммуникационная аппаратура, авиационно-космическая и военная техника, транспорт, системы обеспечения безопасности и ряд других приложений. В этих приложениях ОСРВ должна обеспечить не только получение необходимого логического результата — отклика на внешние события, но и реализовать требуемые интервалы времени между событиями и откликом или заданную частоту приема внешних данных и выдачи результатов.
Современные ОСРВ должны удовлетворять ряду противоречивых требований: малый объем, достаточный для размещения в резидентной памяти системы; малое время отклика; реализация многозадачного режима с гибким механизмом приоритетов, наличие сервисных функций и средств поддержки для разработки прикладных программ и ряд других. В настоящее время разработчику систем предлагается ряд ОСРВ, имеющих различные характеристики и прошедших апробацию в многочисленных областях применения, что позволяет ему найти компромиссное решение для выполнения поставленной задачи. Наиболее часто в системах на базе микропроцессоров и микроконтроллеров фирмы Motorola используются следующие ОСРВ: OS-9 фирмы Microware Systems; VxWorks фирмы WindRiver Systems; LynxOS фирмы Lynx Real-Time Systems; pSOS+ фирмы Integrated Systems; QNX фирмы Quantum Software Systems; VRTX/OS 3.0 фирмы Ready Systems; Nucleus фирмы Accelerated Technology; RTXC фирмы Embedded System Products; OSE фирмы Enea Data, Precise/MQX фирмы Intermetrics Microsystems Software; VMEexec фирмы Motorola.
Подразделяют ОСРВ на два класса - системы "жесткого" и "мягкого" реального времени (РВ). Системы "жесткого" РВ имеют минимальные объем и время отклика, но обладают ограниченными сервисными средствами. Типичным примером ОСРВ этого класса служит VMEexec. Системы "мягкого" РВ требуют большего объема памяти, имеют более длительное время отклика, но удовлетворяют широкому спектру требований пользователя по режиму обслуживания задач, уровню предоставляемого сервиса. Примером такой ОСРВ может служить OS-9/9000.
Однако для современных ОСРВ данная классификация является весьма условной. Ряд ОСРВ, относящихся к классу "жестких", имеют средства интерфейса, которые позволяют, в случае необходимости, использовать высокоэффективные отладчики или интегрированные среды разработки, обеспечивая, таким образом, пользователя набором средств поддержки программирования-отладки систем. Например, VMEexec может использоваться совместно с интегрированной средой MULTI фирмы GreenHills Software, VxWorks с интегрированной средой Tornado, в составе которой поставляются отладчик CrossWind и GNU-компиляторы фирмы Cygnus Support, VRTX и pSOS с отладчиком XRAY и компиляторами фирмы Microtec Research. С другой стороны, системы "мягкого" РВ реализуются по модульному принципу, что позволяет использовать только те средства, которые необходимы в данном приложении. В результате для конкретного применения достигается существенное сокращение объема необходимой памяти и времени отклика. Например, для ядра OS9/9000 время отклика не превышает 20 мкс (для VMEexec, VxWorks, pSOS - менее 10 мкс), что является вполне достаточным для многих приложений.
Для создания многопроцессорных систем, работающих в режиме реального времени (РВ), необходимо базовое программное обеспечение, а именно операционная система. ПО этого направления делится на две большие группы. К первой группе можно отнести небольшие модули, загружаемые на ЦОС-процессоре, а также библиотеки подпрограмм для основного процессора, позволяющие реализовать обмен данными. ЦОС-процессор в такой системе является подчиненным процессором, управляемым основным (host-процессором). Организация функций систем РВ основана на обработке прерываний и механизме обмена сообщениями. Главное достоинство этих систем – небольшая цена. К системам этого типа можно отнести VCOS и DEASY.
Вторая группа операционных систем – это операционные системы реального времени типа Spox или Multiprox. Цена этих систем составляет порядка 20-40 тыс. долларов, но возможности их значительно выше. Операционная система Spox фирмы Spectron Microsystems – одна из ведущих систем, используемых в системах РВ для различных применений, в том числе на платформах с модулями ЦОС. Spox – это специализированная операционная система реального времени, создающая операционное окружение для приложений по обработке данных в реальном режиме.
Другая система – Multiprox фирмы Comdisco. Multiprox – это система разработки, которая позволяет инженерам графически формировать приложения и разделять ЦОС-задачи для нескольких ЦОС-процессоров.
2. Операционная система Spox
Spox (создана фирмой Spectron в 1987 г.) является операционной системой, которая структурирована для обработки сигналов и приложений с интенсивной математикой. Это высокоуровневое окружение для приложений имеет простые в использовании свойства, включая независимый от устройств ввод-вывод, удобные установки процессора и интерфейс с основной машиной (имеется в виду основная ОС). Spox обеспечивает объектно-ориентированную модель для ЦОС и математической обработки.
В последние годы фирма Spectron ввела OSPA (открытая архитектура обработки сигналов) – расширение к Spox для ЦОС-приложений на основной машине. Запускаясь под MS Windows, OSPA обеспечивает интерфейс на уровне основной машины. Используя этот интерфейс, host-приложения могут планировать и контролировать работу многочисленных программ на ЦОС-сопроцессорах (но это не параллельная обработка). OSPA является своего рода интерфейсом API (интерфейсом прикладных программ), который облегчает интеграцию ЦОС-обработки в интерактивное приложение.
Spectron изначально развивал Spox для TMS320C30, но сейчас операционная система запускается также и на Motorola 96002, TI C40 и Analog Device 21020. Spectron также выпускает версию Spox для параллельной обработки. Используемая модель обработки сообщений поддерживает многозадачность. Многозадачное расширение построено вокруг примитивов, основанных на сообщениях, и может обеспечить высокоскоростную передачу данных через каналы ввода-вывода. Spox позволяет совместно использовать память, установленную на отдельном модуле. SPOX поставляется в следующих четырех основных конфигурациях.
Однородные встраиваемые системы.Процессор ЦОС играет роль как общецелевого, так и специализированного процессора. По существу, ЦОС-процессор замещает специализированный контроллер. Со SPOX ЦОС-процессор одновременно выполняет алгоритмы обработки сигналов вместе со сложным контролем по связи задач, прежде выполняемых на специализированных контроллерах. Для приложений, требующих дополнительных мощностей, можно просто использовать дополнительные ЦОС-процессоры. SPOX поддерживает многопроцессорность.
Разнородные встраиваемые системы.Встроенные компьютерные системы реального времени с полными чертами операционной системы (например, VXWorks, OS-9, LynxOS) выполнены на основе ЦОС-подсистем. Это традиционная конфигурация, где ЦОС-подсистема прибавляется к встраиваемой компьютерной системе. Извлекая выгоду из приложений ЦОС в этих системах, Spectron предлагает сбалансированный подход, объединяющий традиционные встраиваемые компьютерные системы (используемые в промышленности) и DSP. Это открывает новый диапазон возможностей для проектирования встроенного управления.
Компьютерные интегрированные системы.В данной конфигурации рабочие станции контролируют ЦОС-подсистемы. Приложение ЦОС запускается в привычном интерактивном окружении (MS-Winows, Unix, DOS), выполняя приложение как тест или измерение, мониторинг контроля процесса, медицинские представления, сбор данных. Здесь приложение имеет ресурсы как основной, так и ЦОС-системы, действуя под управлением рабочей станции.
Мультимедиа системы.Компьютер требует мощных вычислительных затрат по воспроизведению мультимедийных приложений, что соответствует задачам ЦОС: аудиозапись и воспроизведение, видео в реальном режиме, распознавание речи, синтез звука, телекоммуникационные функции, такие, как факс, модем. ЦОС-модуль размещается либо на материнской плате, либо на дополнительной плате, а SPOX усиливает возможности мультимедиа в привычном пользовательском окружении.
SPOX поддерживает высокопроизводительную многозадачность, обработку прерываний, управление памятью, ввод-вывод в реальном времени и большой набор функций по обеспечению взаимосвязи между задачами и процессорами. SPOX имеет математическую и специализированную ЦОС-библиотеку функций, многие из которых написаны на ассемблере для повышения производительности. SPOX поддерживает модель объектно-ориентированного программирования над векторами, матрицами и фильтрами. Для обеспечения этого имеется символьный отладчик и компиляторы языков высокого уровня, таких, как Си. Библиотека SPOX может использоваться на различных платформах, позволяя сосредоточиться на создании собственного приложения, не отвлекаясь на зависимость от платформы.
3. Операционная система Multiprox
Второе направление в развитии ПО – это Multiprox фирмы Comdisco, – пакет, который является новым выбором SPW (Signal Processing Workstation). Используя инструментальное множество, инженеры могут определять ЦОС-приложения графически, используя графические объекты, которые представляют компоненты ЦОС- обработки. Multiprox позволяет инженерам выделять разделы среди потоков данных, рисовать диаграмму течения данных и определять порции, работающие на разных процессорах.
Дополнительно SPW-инструментальное множество и Multiprox автоматически преобразуют диаграммы к процессорно-зависимому Си-коду и встраивают в ПО связи или межпроцессорную коммуникацию, чтобы передавать данные от одного процессора другому. Диаграммы потоков данных преобразуются в Си-программу, содержащую подпрограммы, некоторые из которых написаны на ассемблере и вручную оптимизированы. Таким образом, инженер может использовать инструменты, чтобы распределять высокоуровневое ПО на различные процессоры или смешивать процессоры.
4. Операционная система VCOS
VCOS (Visible Caching Oparating System) делает процессоры ЦОС сопроцессорами. VCOS – переносимая, многозадачная и многопроцессорная операционная система реального времени. VCAS (VCOS Application Server) – резидентная на host-системе программа, загружает и связывает ЦОС-задачи и обеспечивает управление памятью и буферизацию ввода-вывода между host-и ЦОС-процессорами.
VCOS является “минимальной” операционной системой – она занимает менее 400 32-разрядных слов в памяти процессора. ОС использует память host-системы для запоминания программы и данных. Она использует ее как ресурс, чтобы кэшировать данные и код для более быстрой обработки на процессоре. VCOS является “подчиненной” по отношению к host ОС, которая располагает и контролирует VCOS структуры данных, избегая таким образом соперничества между подсистемами при доступе к памяти. VCOS выполняется в высоко приоритетном режиме.
VCOS поставляется вместе с полной библиотекой ЦОС-функций для мультимедийных приложений. Эти приложения включают V.32 модем, V.29 FAX модем, видеозапись, обработку речи, графику, функции сжатия аудио- и видеоинформации.
5. Операционная система DEASY
Операционная система DEASY предназначена для разработки, отладки и выполнения программ ЦОС для процессорных модулей DSP3x фирмы “Инструментальные системы”. DEASY – однозадачная система реального времени. Ни одна из системных функций не блокирует обработку внешних событий (прерываний процессора) на величину более 500 нс.
Основная концепция при разработке программ с использованием DEASY заключается в том, что вокруг сигнального процессора создается виртуальная операционная среда, позволяющая ему играть роль центрального процессора для всего вычислительного комплекса, построенного на базе ПК. Таким образом, обеспечивается прозрачный доступ процессора ЦОС ко всем ресурсам ПК, включая экран монитора, клавиатуру, дисковые устройства, память, порты ввода-вывода и т.д. При этом облегчается процесс переноса программ из другой среды программирования и быстрое прототипирование программ обработки сигналов с использованием традиционных способов.
Операционная система DEASY включает набор библиотек и утилит для составления и отладки прикладных программ ЦОС.
Библиотека System.a30 содержит набор функций для управления процессором TMS320C30 и доступа к его внутренним регистрам из Си-программ.
Библиотека Host.lib состоит из функций для инициализаций, загрузки, управления и обмена информацией между платой ЦОС и ПК.
Библиотека Deasy.a30 содержит набор функций-аналогов библиотеки компилятора Borland C и используется для “прозрачного“ доступа к ресурсам ПК из прикладной программы, выполняемой на плате ЦОС.
Библиотека Bgi.a30 включает в себя функции-аналоги графической библиотеки компилятора Boland C и используется для доступа к графическим ресурсам IBM PC.
Исполняющая среда Deasy.exe предназначена для загрузки и выполнения прикладных программ, составленных с использованием приведенных выше библиотек. Она также содержит простейший диалоговый монитор интерактивного взаимодействия с платой ЦОС.
Символьный отладчик Kg30.exe, или символьный отладчик Cq30.exe, предназначен для отладки прикладных программ, выполняемых на плате ЦОС.
Библиотеки системных функций System и Host. Для организации работы многозадачного режима необходимо обмениваться сообщениями, которые отображают текущее состояние работы программ. Например, после окончания вычислений на одном процессоре (DSP) необходимо сообщить центральному процессору (CPU) о том, что он может забрать данные. При пересылке данных с CPU на DSP необходимо сообщить DSP, что он должен производить расчет. Библиотеки системных функций System и Host позволяют организовать обмен сообщениями и данными.
Библиотека System предназначена для компоновки с программами пользователя, написанными на языке Си или на Ассемблере для процессора TMS320C30. Библиотека Host предназначена для управления платой DSP со стороны ПК из программы пользователя, написанной на языке Си. Данная библиотека поставляется для компиляторов: Borland C/C++, Microsoft C, Watcom C.
6. Операционная система UNIX
Операционная система UNIX представляет собой многозадачную, многопользовательскую операционную систему и является в настоящее время одной из наиболее распространенных в мире. Она была первоначально разработана в 1970-е годы в AT&T Bell Laboratories. Особое внимание к переносимости, интерфейс пользователя, построенный на немногих базовых принципах, и возможность объединения различных UNIX-систем в сети независимо от аппаратной платформы очевидным образом способствовали успеху и распространению UNIX.
С момента своего появления система UNIX непрерывно развивалась и в настоящее время существует в нескольких модификациях. Основными ее распространителями являются компании AT&T Bell Laboratories и Berkeley Software Distribution. Почти все производители вычислительной техники предлагают UNIX либо как коммерческий продукт третьих фирм, либо как специально адаптированную версию для собственной аппаратной платформы. Некоторые специальные предложения отличаются скорее особенностями лицензирования, а не различием в выполняемых ими функциями. Кроме того, для сохранения совместимости и переносимости версии UNIX разных производителей не могут слишком сильно отличаться друг от друга.
В UNIX были введены средства, которые впоследствии были позаимствованы другими операционными системами. На базе UNIX была разработана операционная система OSF/1, а многие функции были включены в Windows NT. UNIX также явилась основной базой для разработки важных коммуникационных интерфейсов, в частности протокола TCP/IP и протокола пользовательского терминала X Window.
UNIX состоит из небольшого ядра, управляющего системными ресурсами (процессор, память и ввод/вывод), а остальная часть процедур операционной системы, и в частности управление файловой системой, работают как пользовательские процессы. Типичная операционная система UNIX содержит 10000-20000 строк на языке С и 1000-2000 строк машинно-ориентированных программ на ассемблере, которые разрабатываются отдельно для каждой аппаратной платформы. Ядро представляет собой единую резидентную программу размером от 100 Кбайт до 1 Мбайт в зависимости от платформы и выполняемых функций. При переносе системы UNIX на конкретную платформу требуется переписать заново только машинно-зависимую часть ядра. Это означает, что UNIX может работать на многих аппаратных платформах с идентичным системным интерфейсом.
Ядро UNIX имеет недостаточно продуманную структуру. Это следствие ее быстрого успеха и распространения, поскольку каждая новая версия должна была быть совместима с предыдущей. Первоначально система UNIX была разработана как многопользовательская, а не для приложений реального времени. Из-за того, что подпрограммы операционной системы работают как пользовательские процессы, но с наивысшим приоритетом, назначенным системой, невозможно прерывать также те системные вызовы, выполнение которых занимает много времени, что увеличивает время реакции системы. Это является существенным недостатком для задач реального времени, особенно управляемых прерываниями. В UNIX используется довольно сложное описание контекста, что увеличивает время переключения процессов. Из-за того, что в UNIX все операции с каналом построены на основе переключения процессов, применение этого механизма для связи между процессами в приложениях реального времени может приводить к задержкам.
Стандартно процессы в UNIX протекают с разделением времени. Для того чтобы дать всем процессам возможность исполняться, применяется динамическое распределение приоритетов. Процессу, готовому для исполнения, сначала присваивается его номинальный приоритет. Во время исполнения значение этого приоритета уменьшается до тех пор, пока он не становится меньше приоритета следующего из ожидающих процессов, который после этого выбирается для исполнения. В результате процессы с более высоким начальным приоритетом получают большую долю процессорного времени, и при этом все процессы периодически исполняются. Системные обращения синхронизированы с вызывающим процессом - он должен ждать, пока запрошенная операция не выполнится и ему не будет возвращено управление.
Важной особенностью, реализованной в UNIX, является одинаковая трактовка всех устройств. Внешние устройства ввода/вывода рассматриваются как файлы. Это существенно упрощает программы, требующие определенной гибкости, так как можно осуществить перенаправление ввода/вывода между файлами или внешними устройствами, такими как локальный или удаленный терминал или принтер, без изменения кода программы. Это также важно и с точки зрения машинной независимости программ.
Общим и вызывающим критику недостатком UNIX является его недружественный пользовательский интерфейс. Все еще в ходу старые и непонятные команды, а если и есть заменяющие их, то с именами или сокращениями, которые столь же неестественны, как и предыдущие. В некоторых системах пользовательские оконные интерфейсы и меню способны в основном "транслировать" выбранные действия в стандартные команды UNIX. Положительной особенностью команд UNIX является то, что благодаря стандартизации ввода/вывода и механизму каналов несколько команд можно объединить в одной строке, причем выход одной команды является входом следующей. Такая техника позволяет для выполнения сложных операций вместо длинных командных файлов использовать всего несколько строк.
Хотя в начале UNIX была многозадачной операционной системой, не предназначенной для работы в реальном времени, из-за широкого распространения в научной и технической среде стала очевидной необходимость ее адаптации и к задачам реального времени. Поэтому новые версии поддерживают такие функциональные элементы систем реального времени, как семафоры, разделяемую память, обмен сигналами между процессами, приоритетное управление задачами и прямой доступ к внешним устройствам. POSIX представляет собой машинно-независимый интерфейс операционной системы, базирующийся на UNIX, определенный стандартом IEEE 1003.1-1988.
7. Операционная система OSF/1 и DСЕ
Первоначальные версии UNIX не требовали лицензий и были доступны практически всем для свободного использования, что отчасти объясняет популярность этой системы. При выпуске System V компания AT&T решила распространять ее только с оплатой лицензий. Некоторые наиболее крупные производители ЭВМ - Digital, Equipment, Hewlett Packard, IBM и др. - отреагировали на это, создав организацию Open Software Foundation (OSF) для того, чтобы не зависеть от диктата одной единственной компании-поставщика операционных систем. OSF разработала UNIX-coвместимую операционную систему, а также другие продукты без лицензионных ограничений со стороны одной компании.
OSF/1 является модульной операционной системой, основанной на Mach, машинно-независимом мультипроцессорном ядре, разработанном в Carnegie-Mellon University (г. Питтсбург, США) в качестве инструмента для эмуляции других операционных систем. На основе Mach действительно удается одновременно эксплуатировать различные операционные системы на одной ЭВМ.
Для обеспечения переносимости OSF/1 совместима с AT&T UNIX System V и спецификациями программных интерфейсов Berkeley. Поскольку Mach и OSF/1 не содержит какого-либо кода UNIX, проблема лицензирования со стороны третьих компаний полностью снята.
В дополнение к средствам UNIX OSF/1 предлагает собственный набор функций, облегчающих разработку и выполнение программ. OSF/1 предназначена для работы в сетевой среде и поддерживает протокол TCP/IP. Файловая система OSF/1 также совместима со службой NFS протокола TCP/IP.
OSF разработала и другие продукты для распределенной вычислительной среды. OSF/Motif является графическим интерфейсом пользователя, обеспечивающим стандартное взаимодействие приложения с графическим терминалом.
Распределенная вычислительная среда (Distributed Computing Environment - DCE) представляет собой набор служб и средств для разработки, исполнения и поддержки приложений в распределенной среде. DСЕ может быть интегрирована с OSF/1, но является независимой от нее и в действительности может эксплуатироваться на базе других операционных систем.
8. Операционная система VAX/VMS
VMS является операционной системой для ЭВМ компании Digital Equipment с 32-разрядным процессором серии VAX. Ее популярность в приложениях управления связана в основном с качеством техники, на которой она используется, и большим количеством предусмотренных средств разработки. VMS может применяться как в среде реального времени, так и в многопользовательской среде с соответствующими средствами защиты.
VMS предоставляет широкий набор функций, стандартный и ясный интерфейс для прямых обращений из программ. Это позволяет осуществлять интеграцию любых языков со всеми функциями операционной системы. Из функций реального времени VMS имеет почтовые ящики в форме логических, состоящих из записей файлов, возможность создания резидентных подпрограмм и обработку прерываний. Процесс в VMS может управлять условиями своего собственного исполнения (приоритет, распределение памяти), создавать другие процессы и управлять их исполнением. Иерархическое управление препятствует процессам с низким приоритетом модифицировать параметры исполнения процессов с высоким приоритетом.
Как и во всех больших операционных системах, в VMS возникают проблемы в случаях, когда предъявляются жесткие требования по времени. По этой причине и ввиду популярности системы VMS, была разработана специальная версия, приспособленная для приложений реального времени, которая называется VAX/ELN. Она состоит из двух различных продуктов - рабочей среды для исполнения прикладных программ на целевой ЭВМ и пакета для разработки программ с компиляторами для различных языков. Разработка программ осуществляется на большом комплексе, имеющем ресурсы для подготовки системы, которая в итоге содержит только программные модули, необходимые для конкретного приложения. Затем в окончательном виде система загружается на рабочую ЭВМ.
Таким образом, операционная система предоставляет процессам логическую среду, состоящую из времени ЦП и оперативной памяти. Операционные системы для многопользовательских приложений и приложений реального времени имеют много общего, но техника программирования должна быть разной - приложения реального времени могут требовать времени реакции порядка 1 мс. При программировании в реальном времени используются специальные функции для координации работы различных процессов. Для обычных программ эти функции не требуются. Кроме этого, программы реального времени управляются прерываниями и могут явно ссылаться на время.
Центральная проблема многозадачного программирования и программирования в реальном времени - координация доступа к защищенным ресурсам. Существует много общего между распределением процессорного времени, защитой ресурсов и управлением доступом к общей шине. Во всех этих случаях ресурс - процессорное время, память, шина - в определенном смысле ограничен и должен распределяться между различными объектами безопасно, эффективно и справедливо. Стратегия разделения ресурсов, которая может основываться на простом циклическом или сложном динамическом механизме планирования, должна позволять избегать тупиков и блокировок, обеспечивать выделение ресурсов всем запрашивающим объектам и максимальную эффективность исполнения процессов. На нижнем уровне наиболее простым средством синхронизации является инструкция test_and_set. Наиболее часто используемые методы синхронизации и связи — это семафоры и почтовые ящики, которые в разных операционных системах реализуются по-разному.
Результаты теории параллельного программирования играют важную роль на практике, так как соответствующие решения подкреплены формальными доказательствами. Это справедливо в особенности для систем реального времени, поскольку тестирование программ в этом случае представляет особую трудность. Применение проверенных методов дает разумную гарантию правильности соответствующих приложений.
Лекция 3.6. Операционные системы реального времени OS-9 и VxWorks
1. Операционная система реального времени OS-9.
2. Операционная система VxWorks.
1. Операционная система реального времени OS-9
В качестве примера современной ОСРВ рассмотрим OS-9, которая широко используются в системах автоматизации производства и телекоммуникационных системах, реализованных на базе микропроцессоров и микроконтроллеров фирмы Motorola. Эта ОСРВ имеет две версии: OS-9 написана на языке Ассемблера Motorola 68K и предназначена для работы с семействами М680х0 и М683хх, OS-9000 написана на языке С и может работать с семействами МРС6хх, МРС5хх, MPCSxx, MCF52xx, а также с микропроцессорами ряда других производителей: Intel 486, Pentium, SPARC, MIPS. Обе версии обеспечивают полную совместимость объектных кодов, поэтому для них обычно используется общее название OS-9. В качестве инструментального компьютера OS-9 использует IBM-PC, работающие в среде Windows, или рабочие станции SUN, HP, IBM RS/6000 с операционными системами типа UNIX.
Характерными особенностями OS-9 являются модульность и гибкость ее структуры. Модульность обеспечивает возможность конфигурации целевой ОСРВ в соответствии с классом решаемых задач. За счет исключения неиспользуемых модулей достигается сокращение объема памяти и стоимости системы. Гибкость структуры позволяет достаточно просто и быстро производить реконфигурацию системы, расширение ее функциональных возможностей.
Все функциональные компоненты OS-9 - ядро реального времени, файловые менеджеры, средства (OS-9 kernel), средства общего управления внешними устройствами (I/O man), разработки - реализованы в виде автономных модулей (рис.1). Комбинируя эти модули, разработчик может создавать целевые операционные системы различной конфигурации и функциональных возможностей - от несложных резидентных ОСРВ, хранящихся во внутреннем ПЗУ микроконтроллера, до сложно-функциональных многопользовательских систем разработки. Все модули OS-9 могут размещаться в ПЗУ. Любые модули могут удаляться или добавляться с помощью простых команд, не требующих повторной компиляции или перекомпоновки.
OS-9 предоставляет пользователю возможность выбора ядра в зависимости от функционального назначения системы.
Ядро Atomic имеет малый объем (28 Кбайт) и обеспечивает минимальное время отклика. Например, при использовании микропроцессора MC68040 с тактовой частотой 25 МГц время реакции ядра на запрос прерывания составляет всего 3 мкс, что соответствует быстродействию систем "жесткого" РВ. Это ядро реализует минимальное число сервисных функций (дистанционную загрузку, связь с локальной сетью, управление ведомыми микроконтроллерами) и применяется в системах, встраиваемых в различную аппаратуру.