Лекция 5.2. Аппаратные средства поддержки проектирования и отладки систем реального времени. 162 7 страница

В настоящее время нет общепринятых методологий измерения этого параметра, поэтому он является полем битвы маркетинговых служб произво­дителей систем реального времени. Но уже появился проект сравнения опе­рационных систем реального времени, который включает в себя, в том числе, и разработку методологии тестирования. Рассмотрим времена, которые не­обходимо знать для того, чтобы предсказать время реакции системы. Собы­тия, происходящие на объекте, регистрируются датчиками, данные с датчиков передаются в модули ввода-вывода (интерфейсы) системы. Модули вво­да-вывода, получив информацию от датчиков и преобразовав ее, генерируют запрос на прерывание в управляющем компьютере, подавая ему тем самым сигнал о том, что на объекте произошло событие. Получив сигнал от модуля ввода-вывода, система должна запустить программу обработки этого собы­тия. Интервал времени - от события на объекте и до выполнения первой ин­струкции в программе обработки этого события и является временем реак­ции системы на события. Проектируя систему реального времени, разработ­чики должны уметь вычислять этот интервал и знать из чего он складывает­ся.

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

Основанием для оценки времен реакции системы могут служить ре­зультаты тестирования с подробным описанием архитектуры целевой систе­мы, в которой проводились измерения с точным указанием, какие промежут­ки времени измерялись. Некоторые производители операционных систем ре­ального времени результаты такого тестирования предоставляют.

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

Размеры системы.Для систем реального времени важным парамет­ром является размер системы исполнения, а именно суммарный размер ми­нимально необходимого для работы приложения системного набора (ядро, системные модули, драйверы и т. д.). С течением времени значение этого па­раметра уменьшается, тем не менее, он остается важным, и производители систем реального времени стремятся к тому, чтобы размеры ядра и обслужи­вающих модулей системы были невелики. Примеры: размер ядра операци­онной системы реального времени OS-9 на микропроцессорах МС68xxx - 22 Kб, VxWorks - 16 Kб.

Возможность исполнения системы из ПЗУ (ROM).Это свойство операционных систем реального времени - одно из базовых. Оно позволяет создавать компактные встроенные СРВ повышенной надёжности, с ограни­ченным энергопотреблением, без внешних накопителей.

Важным параметром при оценке операционных систем реального вре­мени является набор инструментов, механизмов реального времени, предос­тавляемых системой.

Механизмы систем реального времени.Процесс проектирования конкретной системы реального времени начинается с тщательного изучения объекта. Разработчики проекта исследуют объект, изучают возможные собы­тия на нем, определяют критические сроки реакции системы на каждое со­бытие и разрабатывают алгоритмы обработки этих событий. Затем следует процесс проектирования и разработки программных приложений.

У разработчиков СРВ введено понятие «идеальная операционная система реального времени», в которой приложения реального времени разрабатываются на языке событий объекта. Такая система имеет свое назва­ние, хотя и существует только в теории. Называется она: "система, управ­ляемая критическими сроками". Разработка приложений реального времени в этой системе сводится к описанию возможных событий на объекте. В каж­дом описателе события указывается два параметра:

временной интервал - критическое время обслуживания данного собы­тия;

адрес подпрограммы его обработки.

Всю дальнейшую заботу о том, чтобы подпрограмма обработки собы­тия стартовала до истечения критического интервала времени, берет на себя операционная система.

Но это теоретически возможный предел. В реальности разработчик должен перевести язык событий объекта в сценарий многозадачной работы приложений операционных систем реального времени, стараясь оптимально использовать предоставленные ему специальные механизмы и оценить вре­мена реакций системы на внешние события при этом сценарии.

Рассмотрим механизмы, используемые в операционных системах ре­ального времени, которые делают систему реального времени предсказуе­мой.

Система приоритетов и алгоритмы диспетчеризации.Базовыми ин­струментами разработки сценария работы системы являются система при­оритетов процессов (задач) и алгоритмы планирования (диспетчеризации) операционных систем реального времени.

В многозадачных ОС общего назначения используются, как правило, различные модификации алгоритма круговой диспетчеризации, основанные на понятии непрерывного кванта времени ("time slice"), предоставляемого процессу для работы. Планировщик по истечении каждого кванта времени просматривает очередь активных процессов и принимает решение, кому передать управление, основываясь на приоритетах процессов (численных зна­чениях, им присвоенных). Приоритеты могут быть фиксированными или ме­няться со временем. Это зависит от алгоритмов планирования в данной ОС. Но рано или поздно, процессорное время получат все процессы в системе.

Алгоритмы круговой диспетчеризации неприменимы в чистом виде в операционных системах реального времени. Основной недостаток - непре­рывный квант времени ("time slice"), в течение которого процессором владе­ет только один процесс. Планировщики же операционных систем реального времени имеют возможность сменить процесс до истечения кванта времени, если в этом возникла необходимость. Один из возможных алгоритмов пла­нирования при этом – алгоритм "приоритетный с вытеснением". Мир операционных систем реального времени отличается богатством различных алгоритмов планирования: динамические, приоритетные, монотонные, адаптивные и пр., цель же всегда преследуется одна - предоставить инструмент, позволяющий в нужный момент времени исполнять именно тот процесс, который необходим.

Механизмы межзадачного взаимодействия.Другой набор механиз­мов реального времени относится к средствам синхронизации процессов и передачи данных между ними. Для операционных систем реального времени характерна развитость этих механизмов. К таким механизмам относятся: се­мафоры, мьютексы, события, сигналы, средства для работы с разделяемой памятью, каналы данных (pipes), очереди сообщений. Многие из подобных механизмов используются и в ОС общего назначения, но их реализация в операционных системах реального времени имеет свои особенности. В ОСРВ - время исполнения системных вызовов почти не зависит от состояния системы, и в каждой ОСРВ есть, по крайней мере, один быстрый механизм передачи данных от процесса к процессу.

Средства для работы с таймерами.Такие инструменты, как средства работы с таймерами, необходимы для систем с жестким временным регла­ментом, поэтому развитость средств работы с таймерами - необходимый ат­рибут операционных систем реального времени. Эти средства позволяют:

измерять и задавать различные промежутки времени (от 1 мкс и выше);

генерировать прерывания по истечении временных интервалов;

создавать разовые и циклические будильники.

В лекции были рассмотрены только базовые, обязательные механизмы, использующиеся в ОСРВ. Кроме того, почти в каждой операционной систе­ме реального времени присутствует целый набор дополнительных, специфи­ческих только для нее механизмов, касающихся системы ввода-вывода, управления прерываниями, работы с памятью. Каждая система содержит также ряд средств, обеспечивающих ее надежность: встроенные механизмы контроля целостности кодов, инструменты для работы с таймерами.

2. Базовые концепции построения операционных систем реального времени

При описании операционной системы часто указываются особенности ее структурной организации и основные концепции, положенные в ее осно­ву.

К базовым концепциям относятся:

Способы построения ядра системы - монолитное ядроили микро­ядерный подход. Большинство ОС использует монолитное ядро, которое компонуется как одна программа, работающая в привилегированном режиме и использующая быстрые переходы с одной процедуры на другую, не тре­бующие переключения из привилегированного режима в пользовательский, и наоборот. Альтернативой является построение ОС на базе микроядра, ра­ботающего также в привилегированном режиме и выполняющего только минимум функций по управлению аппаратурой, в то время как функции ОС бо­лее высокого уровня выполняют специализированные компоненты ОС - сер­веры, работающие в пользовательском режиме. При таком построении ОС работает более медленно, так как часто выполняются переходы между при­вилегированным режимом и пользовательским, но система получается более гибкой - ее функции можно наращивать, модифицировать или сужать, до­бавляя, модифицируя или исключая серверы пользовательского режима. Кроме того, серверы хорошо защищены друг от друга, как и любые пользо­вательские процессы.

Построение ОС на базе объектно-ориентированного подхода дает воз­можность использовать все его достоинства, хорошо зарекомендовавшие се­бя на уровне приложений, внутри операционной системы. Ее основными достоинствами являются: аккумуляция удачных решений в форме стандарт­ных объектов; возможность создания новых объектов на базе имеющихся, с помощью механизма наследования; хорошая защита данных за счет их ин­капсуляции во внутренние структуры объекта, что делает данные недоступ­ными для несанкционированного использования извне; структурированность системы, состоящей из набора хорошо определенных объектов.

Наличие нескольких прикладных сред дает возможность в рамках од­ной ОС одновременно выполнять приложения, разработанные для несколь­ких ОС. Многие современные операционные системы поддерживают одно­временно прикладные среды MS-DOS, Windows, UNIX (POSIX), OS/2 или хотя бы некоторого подмножества из этого популярного набора. Концепция множественных прикладных сред наиболее просто реализуется в ОС на базе микроядра, над которым работают различные серверы, часть которых реали­зуют прикладную среду той или иной операционной системы.

Распределенная организация операционной системы позволяет упро­стить работу пользователей и программистов в сетевых средах. В распределенной ОС реализованы механизмы, которые дают возможность пользовате­лю представлять и воспринимать сеть в виде традиционного однопроцессор­ного компьютера. Характерными признаками распределенной организации ОС являются:

наличие единой справочной службы разделяемых ресурсов;

единой службы времени;

использование механизма вызова удаленных процедур (RPC) для про­зрачного распределения программных процедур по машинам;

многонитевой обработки, позволяющей распараллеливать вычисления в рамках одной задачи и выполнять эту задачу сразу на нескольких компью­терах сети;

наличие других распределенных служб.

3. Монолитная архитектура

Организация монолитной системы представляет собой структуру, у ко­торой ОС написана в виде набора процедур, каждая из которых может вызы­вать другие, когда ей это нужно. При использовании такой техники каждая процедура системы имеет строго определенный интерфейс в терминах па­раметров и результатов, и каждая имеет возможность вызвать любую дру­гую для выполнения необходимой для нее работы.

Для построения монолитной системы необходимо скомпилировать все отдельные процедуры, а затем связать их в единый объектный файл с помо­щью компоновщика. Здесь, по существу, полностью отсутствует сокрытие деталей реализации - каждая процедура видит любую другую процедуру (в отличие от структуры, содержащей модули, в которой большая часть ин­формации является локальной для модуля и процедуры модуля можно вы­звать только через специально определенные точки входа).

Однако даже такие монолитные системы могут иметь некоторую структуру. При обращении к системным вызовам, поддерживаемым операци­онной системой, параметры помещаются в строго определенные места - ре­гистры или стек, после чего выполняется специальная команда прерыва­ния, известная как вызов ядра или вызов супервизора. Эта команда пере­ключает машину из режима пользователя в режим ядра и передает управле­ние операционной системе. Затем операционная система проверяет пара­метры вызова, чтобы определить, какой системный вызов должен быть вы­полнен. После этого операционная система обращается к таблице как к мас­сиву с номером системного вызова в качестве индекса. В k-м элементе таб­лицы содержится ссылка на процедуру обработки системного вызова. Такая организация операционной системы предполагает следующую структуру:

1. Главная программа, которая вызывает требуемую служебную проце­дуру.

2. Набор служебных процедур, выполняющих системные вызовы.

3. Набор утилит, обслуживающих служебные процедуры. В этой модели для каждого системного вызова имеется одна служебная процедура. Утилиты выполняют функции, которые нужны нескольким слу­жебным процедурам. Деление процедур на три уровня показано на рис. 1.

Рисунок 1. – Модель монолитной системы

 

В силу преимуществ объектно-ориентированного подхода приложения создаются на его основе, используя один из языков программирования, наилучшим образом поддерживающий этот подход. Архитектуры же классиче­ских операционных систем реального времени основаны на архитектурах UNIX систем и используют традиционный процедурный подход к програм­мированию. Сочетание объектно-ориентированных приложений и проце­дурных операционных систем имеет ряд недостатков:

1. Происходит разрыв парадигмы программирования: в едином рабо­тающем комплексе (приложение + ОСРВ) разные компоненты используют разные подходы к разработке программного обеспечения.

2. Не используются все возможности объектно-ориентированного под­хода.

3. Возникают некоторые потери производительности из-за разного ти­па интерфейсов в ОСРВ и приложении.

Естественно, возникает идея строить саму СРВ, используя объектно-ориентированный подход. При этом:

- как приложение, так и операционная система полностью объектно-ориентированны и используют все преимущества этого подхода;

- приложение и ОСРВ могут быть полностью интегрированы, посколь­ку используют один объектно-ориентированный язык программирования;

- обеспечивается согласование интерфейсов ОСРВ и приложения;

- приложение может «моделировать» ОСРВ для своих потребностей, заказывая нужные ему объекты;

- единый комплекс (приложение + ОСРВ) является модульным и легко модернизируемым. Идея реализована в ОСРВ SoftKernel, целиком написан­ной на C++. ОСРВ с монолитной архитектурой можно представить в виде:

- прикладного уровня: состоящего из работающих прикладных процес­сов;

- системного уровня: состоящего из монолитного ядра операционной системы, в котором можно выделить следующие части:

а) интерфейс между приложениями и ядром (API);

б) собственно ядро системы;

в) интерфейс между ядром и оборудованием (драйверы устройств). API в таких системах играет двойную роль:

1) управляет взаимодействием прикладных процессов и системы;

2) обеспечивает непрерывность выполнения кода системы (отсутствие переключения задач во время исполнения кода системы).

Основным преимуществом монолитной архитектуры является ее отно­сительная быстрота работы по сравнению с другими архитектурами. Однако, достигается это, в основном, за счет написания значительных частей систе­мы на ассемблере.

Недостатки монолитной архитектуры:

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

2. Ядро не может быть прервано пользовательской задачей. Это может приводить к тому, что высокоприоритетная задача может не получить управ­ления из-за работы низкоприоритетной задачи. Например, низкоприоритет­ная задача запросила выделение памяти, сделала системный вызов, до окон­чания которого сигнал активизации высокоприоритетной задачи не сможет ее активизировать.

3. Сложность переноса на новые архитектуры процессора из-за значи­тельных ассемблерных вставок.

4. Негибкость и сложность развития: изменение части ядра системы требует его полной перекомпиляции.

4. Модульная архитектура на основе микроядра

Модульная архитектура появилась, как попытка убрать узкое место API и облегчить модернизацию системы и перенос ее на новые процессоры.

API в модульной архитектуре играет только одну роль: обеспечивает связь прикладных процессов и специального модуля менеджера процессов. Однако теперь микроядро играет двойную роль:

1) управление взаимодействием частей системы (например, менедже­ров процессов и файлов);

2) обеспечение непрерывности выполнения кода системы (отсутствие переключения задач во время исполнения микроядра).

Недостатки модульной архитектуры фактически те же, что и у моно­литной архитектуры. Проблемы перешли с уровня API на уровень микрояд­ра. Системный интерфейс по-прежнему не допускает переключения задач во время работы микроядра, только сократилось время пребывания в этом со­стоянии. API по-прежнему может быть реализован только на ассемблере, проблемы с переносимостью микроядра уменьшились (в связи с сокращени­ем его размера).

5. Объектная архитектура на основе объектов-микроядер

В этой архитектуре (используемой в ОСРВ SoftKernel) API отсутствует вообще. Взаимодействие между компонентами системы (микроядрами) и пользовательскими процессами осуществляется посредством обычного вы­зова функций, поскольку и система, и приложения написаны на одном языке (C++). Это обеспечивает максимальную скорость системных вызовов.

Фактическое равноправие всех компонент системы обеспечивает воз­можность переключения задач в любое время, то есть система полностью управляема.

Объектно-ориентированный подход обеспечивает модульность, безо­пасность, легкость модернизации и повторного использования кода.

Роль API играет компилятор и динамический редактор объектных свя­зей (linker). При старте приложения динамический linker загружает нужные ему микроядра (в отличие от предыдущих систем, не все компоненты самой операционной системы должны быть загружены в оперативную память). Ес­ли микроядро уже загружено для другого приложения, то оно повторно не загружается, а используется код и данные уже имеющегося микроядра. Это позволяет сократить объем требуемой памяти.

Поскольку разные приложения разделяют одни микроядра, то они должны работать в одном адресном пространстве. Следовательно, система не может использовать виртуальную память и тем самым работает быстрее (так как исключаются задержки на трансляцию виртуального адреса в физиче­ский).

Поскольку все приложения и сами микроядра работают в одном адрес­ном пространстве, то они загружаются в память, начиная с неизвестного на момент компиляции адреса. Следовательно, приложения и микроядра не должны зависеть от начального адреса (как по коду, так и по данным). Это свойство автоматически обеспечивает возможность записи приложений и модулей в ПЗУ, с последующим их исполнением, как в самом ПЗУ, так и в оперативной памяти.

Микроядра по своим характеристикам напоминают структуры, исполь­зуемые в других операционных системах, однако есть и свои различия.

Микроядра и модули. Многие ОС поддерживают динамическую за­грузку компонент системы, называемых модулями. Однако модули не под­держивают объектно-ориентированный подход ввиду того, что микроядро является фактически представителем некоторого класса. Далее, обмен ин­формацией с модулями происходит посредством системных вызовов, что достаточно дорого.

Микроядра и драйверы. Многие ОС поддерживают возможность сво­его расширения посредством драйверов (специальных модулей, обычно слу­жащих для поддержки оборудования). Однако драйверы часто должны быть статически связаны с ядром (образовывать с ним связанный загрузочный об­раз еще до загрузки) и должны работать в привилегированном режиме. Как и модули, они не поддерживают объектно-ориентированный подход и доступ­ны приложениям только посредством системных вызовов.

Микроядра и DLL (Dynamically Linked Libraries, динамически связы­ваемые библиотеки). Многие системы оформляют библиотеки, из которых берутся функции при динамическом связывании, в виде специальных моду­лей, называемых DLL. DLL обеспечивает разделение своего кода и данных для всех работающих приложений, в то время, как для микроядер можно управлять доступом для каждого конкретного приложения. DLL не поддер­живает объектно-ориентированный подход, код DLL не является позиционно-независимым, и потому не может быть записан в ПЗУ.


Лекция 3.2 Механизмы синхронизации и взаимодействия процессов

1. Синхронизация процессов в системах реального времени.

2. Критические секции.

3. Семафоры.

4. События.

 

1. Синхронизация процессов в системах реального времени Организация некоторого порядка исполнения процессов называется синхронизацией(synchronization). Синхронизация процессов является ос­новной функцией многозадачных операционных систем и используется для защиты ресурсов - с помощью механизма синхронизации упорядочивается доступ к ресурсу. То есть, процесс может получить доступ к ресурсу только после того, как другой процесс освободил его. Введение дополнительных пе­ременных для защиты ресурсов не лучший выход, поскольку эти переменные сами становятся общим ресурсом. Существо проблемы состоит в том, что операции проверки и изменения значения переменной защиты разделены во времени и могут быть прерваны в любой момент. Более того, непрерывный контроль значений этих переменных представляет собой излишние затраты процессорного времени.

Существует достаточно обширный класс средств операционных сис­тем, с помощью которых обеспечивается взаимная синхронизация процессов и потоков. Потребность в синхронизации потоков возникает только в муль­типрограммной операционной системе и связана с использованием аппарат­ных и информационных ресурсов вычислительной системы. Синхронизация необходима для исключения гонок и тупиков при обмене данными между потоками, разделении данных, при доступе к процессору и устройствам ввода-вывода.

Ситуации, когда два или более потоков обрабатывают разделяемые данные и конечный результат зависит от соотношения скоростей потоков, называются гонками.

Во многих операционных системах эти средства называются средства­ми межпроцессного взаимодействия.

Выполнение потока в мультипрограммной среде всегда имеет асин­хронный характер. Очень сложно с полной определенностью сказать, на ка­ком этапе выполнения будет находиться процесс в определенный момент времени. Даже в однопрограммном режиме не всегда можно точно оценить время выполнения задачи. Это время во многих случаях существенно зави­сит от значения исходных данных, которые влияют на количество циклов, направления разветвления программы, время выполнения операций ввода-вывода и т. п. Так как исходные данные в разные моменты запуска задачи могут быть разными, то и время выполнения отдельных этапов и задачи в целом является весьма неопределенной величиной.

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

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

Любое взаимодействие процессов или потоков связано с их синхрони­зацией, которая заключается в согласовании их скоростей путем приоста­новки потока до наступления некоторого события и последующей его активизации при наступлении этого события. Синхронизация лежит в основе любого взаимодействия потоков, связано ли это взаимодействие с разделени­ем ресурсов или с обменом данными. Например, поток-получатель должен обращаться за данными только после того, как они помещены в буфер пото­ком-отправителем. Если же поток-получатель обратился к данным до мо­мента их поступления в буфер, то он должен быть приостановлен.

При совместном использовании аппаратных ресурсов синхронизация также совершенно необходима. Когда, например, активному потоку требует­ся доступ к последовательному порту, а с этим портом в монопольном режи­ме работает другой поток, находящийся в данный момент в состоянии ожи­дания, то операционная система (ОС) приостанавливает активный поток и не активизирует его до тех пор, пока нужный ему порт не освободится. Часто нужна также синхронизация с событиями, внешними по отношению к вычис­лительной системе, например реакции на нажатие комбинации клавиш Сtгl+С.

Ежесекундно в системе происходят сотни событий, связанных с распре­делением и освобождением ресурсов, и операционная система должна иметь надежные и производительные средства, которые бы позволяли ей синхрони­зировать потоки с происходящими в системе событиями.

Для синхронизации потоков прикладных программ программист может использовать как собственные средства и приемы синхронизации, так и средства операционной системы. Например, два потока одного прикладного процесса мо­гут координировать свою работу с помощью доступной для них обоих глобаль­ной логической переменной, которая устанавливается в единицу при осуществ­лении некоторого события, например выработки одним потоком данных, нуж­ных для продолжения работы другого. Однако во многих случаях более эффек­тивными или даже единственно возможными являются средства синхрониза­ции, предоставляемые операционной системой в форме системных вызовов. Так, потоки, принадлежащие разным процессам, не имеют возможности вмеши­ваться каким-либо образом в работу друг друга. Без посредничества операционной системы они не могут приостановить друг друга или оповестить о про­изошедшем событии. Средства синхронизации используются операционной системой не только для синхронизации прикладных процессов, но и для ее внутренних нужд.

Обычно разработчики операционных систем предоставляют в распоряже­ние прикладных и системных программистов широкий спектр средств синхро­низации. Эти средства могут образовывать иерархию, когда на основе более про­стых средств строятся более сложные, быть функционально специализирован­ными. Например, средства для синхронизации потоков одного процесса, сред­ства для синхронизации потоков разных процессов при обмене данными и т. д. Часто функциональные возможности разных системных вызовов синхронизации перекрываются, так что для решения одной задачи программист может вос­пользоваться несколькими вызовами в зависимости от своих личных предпоч­тений.

Пренебрежение вопросами синхронизации в многопоточной системе может привести к неправильному решению задачи или даже к краху системы.

2. Критические секции

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

Чтобы исключить эффект гонок по отношению к критическим данным, необходимо обеспечить, чтобы в каждый момент времени в критической секции, связанной с этими данными, находился только один поток. При этом неважно, находится этот поток в активном или в приостановленном состоя­нии. Этот прием называют взаимным исключением. Операционная система использует разные способы реализации взаимного исключения. Некоторые способы пригодны для взаимного исключения при вхождении в критиче­скую секцию только потоков одного процесса, в то время как другие могут обеспечить взаимное исключение и для потоков разных процессов.