
ОС / учебник(см. лекции) Корольковой / глава 2
.pdf
m - число классов ресурсов (например: принтеры это один класс), n - количество процессов, P(n) – процессы, E - вектор существующих ресурсов, E(i) - количество ресурсов класса I, A - вектор доступных (свободных) ресурсов, A(i) - количество доступных ресурсов класса i, С - матрица текущего распределения (какому процессу какие ресурсы принадлежат), R - матрица запросов (какой процесс, какой ресурс запросил)
C(ij) - количество экземпляров ресурса j, которое занимает процесс Pi, R(ij) -
количество экземпляров ресурса j, которое хочет получить процесс Pi .
Общее количество ресурсов равно сумме занятых и свободных ресурсов.
Рассмотрим алгоритм поиска тупиков.
Рис. 2.18 Алгоритм поиска тупиков при наличии нескольких ресурсов каждого типа Если остаются немаркированные процессы, значит, есть тупик.
Рассмотрим работу алгоритма на реальном примере.

Используем алгоритм:
1.Третий процесс может получить желаемые ресурсы, т.к.
R (2 1 0 0) = A (2 1 0 0)
2.Третий процесс освобождает ресурсы. Прибавляем их к A.
А= (2 1 0 0) + (0 1 2 0) =(2 2 2 0). Маркируем процесс.
3.Может выполняться процесс 2. По его завершении А=(4 2 2 1).
4.Теперь может работать первый процесс. Тупиков не обнаружено.
Когда следует искать тупики:
Когда запрашивается очередной ресурс (очень загружает систему).
Периодически, через какой-то определенный промежуток времени (в
интерактивных системах пользователь ощутит замедление работы).
Когда загрузка процессора слишком велика.
2.5.2.3.5Выход из взаимоблокировки
-Восстановление при помощи принудительной выгрузки ресурса. Как правило,
требует ручного вмешательства (например: принтер).
-Восстановление через откат. Состояние процессов записывается в контрольных точках, и в случае тупика можно сделать откат процесса на более раннее состояние, после чего он продолжит работу снова с этой точки.
-Восстановление путем уничтожения процесса. Самый простой способ. Ге обязательно снимать с выполнения все заблокированные процессы. Можно снять только часть из них, при этом освобождаются ресурсы, ожидаемые остальными процессами.
2.5.2.4Динамическое избежание взаимоблокировок
2.5.2.4.1 Траектории ресурсов Рассмотрим модель из двух процессов и двух ресурсов.
А1 - запрос принтера процессом А, А2 - запрос плоттера процессом А,
А3 - освобождение принтера процессом А, А4 - освобождение плоттера процессом А

В1 - запрос плоттера процессом В, В2 - запрос принтера процессом В,
В3 - освобождение плоттера процессом В, В4 - освобождение принтера процессом В.
Рис. 2.19 Динамическое избежание взаимоблокировок Т.к. процессор предоставляется поочередно, траектория может продолжаться только
параллельно осям. Чтобы избежать тупика, процессам надо обойти прямоугольник,
охватывающий всю заштрихованную область.
2.5.2.4.2Безопасные и небезопасные состояния
Вбезопасном состоянии система может гарантировать, что все процессы закончат свою работу.
Рассмотрим систему, в которой существует 10 экземпляров ресурса и 3 процесса.
Процесс А занял 3 экземпляра, но ему необходимо 9. В этой ситуации можно спланировать так, что вначале запускается процесс В, потом С и потом А. Процессы заканчивают работу без тупиковой ситуации.
Рассмотрим другую ситуацию.
Процесс А занял 4 экземпляра ресурса.

Возникает небезопасное состояние, поскольку возможен тупик. В принципе, процесс А может в какой то момент ресурс освободить и тупика не возникнет. Видно, что в этом случае не стоило давать ресурс процессу А.
2.5.2.4.3 Алгоритм банкира для одного вида ресурсов Рассмотрим систему. Банкир может дать 10 кредитов (ресурсы). К нему
попеременно обращаются 4 клиента.
Алгоритм банкира:
1.Банкиру поступает запрос от клиента на получение кредита.
2.Банкир проверяет, приводит ли этот запрос к небезопасному состоянию.
3.Банкир в зависимости от этого дает или отказывает в кредите.
Рис. 2.20 Алгоритм банкира
2.5.2.4.4 Алгоритм банкира для несколько видов ресурсов
Рассмотрим систему:

E=(6342) - существующие ресурсы, P=(5322) - занятые ресурсы, A=(1020) -
доступные ресурсы Алгоритм поиска безопасного или небезопасного состояния:
Рис. 2.21 Алгоритм банкира для несколько видов ресурсов Если состояние безопасное, то ресурс выделить можно, если нет - нельзя.
На практике все эти алгоритмы сложно реализовать.
2.5.2.5Предотвращение условий, необходимых для взаимоблокировок
1.Предотвращение условия взаимного исключения.
Можно минимизировать количество процессов, борющихся за ресурсы. Например, с
помощью спулинга для принтера, когда только демон принтера работает с принтером.
2. Предотвращение условия удержания и ожидания.
Один из способов достижения этой цели заключается в том, что процесс должен запрашивать все необходимые ресурсы до начала работы. Если хоть один ресурс недоступен, то процессу вообще ничего не предоставляется.
3. Предотвращение условия отсутствия принудительной выгрузки ресурса.
Разрешить ОС отбирать ресурсы, но могут быть проблемы.
4. Предотвращение условия циклического ожидания.
Способы предотвращения:
Процесс сначала должен освободить занятый ресурс, прежде чем занять новый.
Можно пронумеровать все ресурсы, и процессы должны получать ресурсы только по возрастающему (убывающему) порядку.
2.5.2.6Системные средства синхронизации процессов
Вслучае синхронизации потоков разных процессов операционная система должна предоставлять потокам системные объекты синхронизации, которые были бы видны для всех потоков, даже если они принадлежат разным процессам и работают в разных адресных пространствах. Примерами таких синхронизирующих объектов ОС являются системные семафоры, мьютексы, события, таймеры и другие.
Чтобы процессы могли разделять синхронизирующие объекты, в разных ОС используются разные методы: возврат указателя на объект, доступного всем родственным процессам, наследующим характеристики общего родительского процесса; указание в запросах на создание объектов синхронизации имен, которые должны быть им присвоены.
Далее эти имена используются разными процессами для манипуляций объектами синхронизации. В таком, случае работа с синхронизирующими объектами подобна работе с файлами (создавать, открывать, закрывать, уничтожать).
Все синхронизирующие объекты могут находиться в двух состояниях:
-сигнальном
-несигнальном (свободном).
Для каждого объекта смысл, вкладываемый в понятие «сигнальное состояние»,
зависит от типа объекта. Так, например, поток переходит в сигнальное состояние тогда,
когда он завершается. Процесс переходит в сигнальное состояние тогда, когда завершаются все его потоки. Файл переходит в сигнальное состояние в том случае, когда завершается операция ввода-вывода для этого файла. Для остальных объектов сигнальное состояние устанавливается в результате выполнения специальных системных вызовов.
Приостановка и активизация потоков осуществляются в зависимости от состояния синхронизирующих объектов ОС.
Потоки с помощью специального системного вызова сообщают операционной системе о том, что они хотят синхронизировать свое выполнение с состоянием некоторого объекта, при этом поток может ожидать установки сигнального состояния не одного объекта, а нескольких. Поток может попросить ОС активизировать его при установке либо одного из указанных объектов, либо всех объектов. В качестве аргумента системного вызова Wait() поток может указать максимальное время, которое он будет ожидать
перехода объекта в сигнальное состояние, после чего ОС должна его активизировать в любом случае. Может случиться, что установки некоторого объекта в сигнальное состояние ожидают сразу несколько потоков. В зависимости от объекта синхронизации в состояние готовности могут переводиться либо все ожидающие это событие потоки, либо один из них.
Синхронизация тесно связана с планированием потоков. Любое обращение потока
ссистемным вызовом Wait(X) влечет за собой действия в подсистеме планирования:
-поток снимается с выполнения и помещается в очередь ожидающих потоков
-из очереди готовых потоков выбирается и активизируется новый поток.
-при переходе объекта в сигнальное состояние ожидающий этот объект поток (или потоки) переводится в очередь готовых к выполнению потоков. В обоих случаях осуществляется перепланирование потоков, при этом если в ОС предусмотрены изменяемые приоритеты и/или кванты времени, то они пересчитываются по правилам,
принятым в этой операционной системе.
2.5.2.6.1 Мьютексы
Объекты-взаимоисключения (мьютексы, mutex - от MUTual EXclusion) позволяют координировать взаимное исключение доступа к разделяемому ресурсу. Сигнальное состояние объекта (т.е. состояние "установлен") соответствует моменту времени, когда объект не принадлежит ни одному потоку и его можно "захватить". Предположим, что мьютекс находится в сигнальном состоянии, в этом случае поток тут же становится его владельцем, устанавливая его в несигнальное состояние, и входит в критическую секцию.
После того как поток выполнил работу с критическими данными, он «отдает» мьютекс,
устанавливая его в сигнальное состояние. Если какой-либо поток ожидает его освобождения, то он становится следующим владельцем этого мьютекса, одновременно мьютекс переходит в несигнальное состояние.
2.5.2.6.2 Системные семафоры Существует еще один метод синхронизации потоков, в котором используются
семафорные объекты API. В семафорах применен принцип действия мьютексов, но с добавлением одной существенной детали. В них заложена возможность подсчета ресурсов, что позволяет заранее определенному числу потоков одновременно войти в синхронизуемый участок кода. Для создания семафора используется функция
CreateSemaphore.
2.5.2.6.3 События События используются в качестве сигналов о завершении какой-либо операции. В
отличие от мьютексов, они не принадлежат ни одному потоку. Объект-событие обычно
используется не для доступа к данным, а для того, чтобы оповестить другие потоки о том,
что некоторые действия завершены. Пусть, например, в некотором приложении работа организована таким образом, что один поток читает данные из файла в буфер памяти, а
другие потоки обрабатывают эти данные, затем первый поток считывает новую порцию данных, а другие потоки снова ее обрабатывают и так далее. В начале работы первый поток устанавливает объект-событие в несигнальное состояние. Все остальные потоки выполнили вызов Wait(X), где X — указатель события, и находятся в приостановленном состоянии, ожидая наступления этого события. Как только буфер заполняется, первый поток сообщает об этом операционной системе, выполняя вызов Set(X). Операционная система просматривает очередь ожидающих потоков и активизирует все потоки, которые ждут этого события.
2.5.2.6.4 Ждущие таймеры
Ждущий таймер (waitable timer) представляет собой новый тип объектов синхронизации, поддерживаемый в Windows NT версии 4.0 и выше. Это полноценный объект синхронизации, который может использоваться для организации задержки в одном или нескольких приложениях.
Ждущий таймер работает в трех режимах. В режиме «ручного сброса» таймер переходит в установленное состояние при истечении заданной задержки и остается установленным до тех пор, пока функция SetWaitableTimer не задаст новую задержку. В
режиме «автоматического сброса» таймер переходит в установленное состояние при истечении заданной задержки и остается установленным до первого успешного вызова функции ожидания. Каждый раз при истечении времени задержки разрешается выполнение лишь одной нити. Наконец, ждущий таймер может выполнять функции интервального таймера, который перезапускается с заданной задержкой после каждого срабатывания объекта.
Главная особенность, отличающая ждущие таймеры от системных, — то, что ждущие таймеры могут совместно использоваться несколькими приложениями.
Процессы получают дескрипторы ждущих таймеров так же, как они получают дескрипторы мьютексов: дублированием, наследованием или открытием по имени.
2.5.2.6.5 Сигналы Сигнал или виртуальное прерывание является сообщением, которое система
посылает процессу или один процесс посылает другому. Когда процесс получает сигнал,
выполнение программы процесса прерывается, и управление передается на подпрограмму
(функцию) - обработчик сигнала. После выполнения обработчика сигнала выполнение прерванной программы возобновляется с той точки, на которой она была прервана.
В операционной системе предусмотрено большое число типов сигналов, но большинство из этих типов зарезервировано для системных целей - это сигналы, которые операционная система посылает процессу. Однако есть и сигналы, которыми процессы могут обмениваться между собой. По умолчанию реакция на большинство сигналов -
прекращение процесса, получившего сигнал, то есть, если процесс получает сигнал,
обработка которого в нем не предусмотрена, то процесс-получатель сигнала завершается.
Однако для большинства типов сигналов процесс может установить обработчик данного сигнала или установить игнорирование данного сигнала.
2.5.2.6.3 Мониторы Хоара Монитор – это набор процедур и информационных структур, которыми процессы
пользуются в режиме разделения, причем в фиксированный момент времени им может пользоваться только один процесс.
Отличительная особенность монитора в том, что в его распоряжении находится некоторая специальная информация, предназначенная для общего пользования, но доступ к ней можно получить только при обращении к этому монитору. Монитор не является процессом, это пассивный объект, который приходит в активное состояние только тогда,
когда какой-то объект обращается к нему за услугами.
2.5.3Обмен данными между процессами и потоками
Операционная система, имея доступ ко всем областям памяти, играет роль посредника в информационном обмене прикладных потоков. При необходимости в обмене данными поток обращается с запросом к ОС. ОС, пользуясь своими привилегиями, создает различные системные средства связи. Многие из средств межпроцессного обмена данными выполняют также и функции синхронизации: в том случае, когда данные для процесса-получателя отсутствуют, последний переводится в состояние ожидания средствами ОС, а при поступлении данных от процесса-
отправителя процесс-получатель активизируется.
Передача может осуществляться несколькими способами:
разделяемая память;
канал (pipe, конвейер) - псевдофайл, в который один процесс пишет, а другой читает;
сокеты - поддерживаемый ядром механизм, скрывающий особенности среды и позволяющий единообразно взаимодействовать процессам, как на одном компьютере,
так и в сети;
почтовые ящики (только в Windows), однонаправленные, возможность
широковещательной рассылки;
вызов удаленной процедуры, процесс А может вызвать процедуру в процессе В,
иполучить обратно данные.
2.5.3.1Конвейеры (каналы)
Существует два способа организовать двунаправленное соединение с помощью каналов: безымянные и именованные каналы. Канал представляет собой буфер в оперативной памяти, поддерживающий очередь байт по алгоритму FIFO. Для программиста этот буфер выглядит как безымянный файл, в который можно писать и читать, осуществляя тем самым обмен данными. Обмениваться данными могут только родственные процессы, точнее процессы, которые имеют общего прародителя, создавшего данный конвейер. Связано это с тем, что конвейер не имеет имени, обращение к нему происходит по дескриптору, который имеет локальное для каждого процесса значение.
Безымянные (или анонимные) каналы позволяют связанным процессам передавать информацию друг другу. Обычно, безымянные каналы используются для перенаправления стандартного ввода/вывода дочернего процесса так, чтобы он мог обмениваться данными с родительским процессом. Чтобы производить обмен данными в обоих направлениях, необходимо создать два безымянных канала. Родительский процесс записывает данные в первый канал, используя его дескриптор записи, в то время как дочерний процесс считывает данные из канала, используя дескриптор чтения.
Аналогично, дочерний процесс записывает данные во второй канал и родительский процесс считывает из него данные. Безымянные каналы не могут быть использованы для передачи данных по сети и для обмена между несвязанными процессами.
Именованные конвейеры. Такие конвейеры имеют имя, которое является записью в каталоге файловой системы ОС, поэтому пригодны для обмена данными между двумя произвольными процессами или потоками этих процессов. Именованный конвейер является специальным файлом типа FIFO и не имеет области данных на диске.
Создается именованный конвейер с помощью того же системного вызова, который используется для создания файлов любого типа, но только с указанием в качестве типа файла параметра FIFO. Системный вызов порождает в каталоге запись о файле FIFO с
заданным именем, после чего любой процесс может открыть этот файл и передавать данные другому процессу, также открывшему файл с этим именем.
Именованные каналы используются для передачи данных между независимыми процессами или между процессами, работающими на разных компьютерах. Обычно,
процесс сервера именованных каналов создает именованный канал с известным именем или с именем, которое будет передано клиентам. Процесс клиента именованных каналов,
зная имя созданного канала, открывает его на своей стороне с учетом ограничений,