Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Архив WinRAR / лекции / операционные системы.pdf
Скачиваний:
107
Добавлен:
12.02.2015
Размер:
2.27 Mб
Скачать

149

4.2. Примеры тупиковых ситуаций и причины их возникновения

Для понимания основных причин возникновения тупиков рассмотрим несколько простых характерных примеров.

Пример тупика на ресурсах типа CR

Пусть имеются три процесса ПР1, ПР2 и ПРЗ, которые вырабатывают соответственно сообщения Ml, M2 и МЗ. Эти сообщения представляют собой ресурсы типа CR. Пусть процесс ПР1 является “потребителем” сообщения МЗ, процесс ПР2 получает сообщение Ml, а ПРЗ – сообщение М2 от процесса ПР2, то есть каждый из процессов является и “поставщиком” и “потребителем” одновременно, и вместе они образуют “кольцевую” систему (рис. 3.13) передачи сообщений через почтовые ящики (ПЯ). Если связь с помощью этих сообщений со стороны каждого процесса устанавливается в порядке, изображенном в листинге 3.1, то никаких трудностей не возникает. Однако перестановка этих двух процедур в каждом из процессов (листинг 3.2) вызывает тупик:

ПР1

ПЯ

ПЯ

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ПР3

 

ПР2

 

 

 

 

 

ПЯ

Рис. 3.13. Кольцевая схема взаимодействия процессов

Листинг 3.1. Вариант без тупиковой ситуации

ПР1:

ПОСЛАТЬ СООБЩЕНИЕ (ПР2, M1, ПЯ2); ЖДАТЬ СООБЩЕНИЕ (ПРЗ, МЗ, ПЯ1);

ПР2:

150

ПОСЛАТЬ СООБЩЕНИЕ (ПРЗ, М2, ПЯЗ); ЖДАТЬ СООБЩЕНИЕ (ПР1, M1, ПЯ2);

ПРЗ:

ПОСЛАТЬ СООБЩЕНИЕ (ПР1, МЗ, ПЯ1); ЖДАТЬ СООБЩЕНИЕ (ПР2, М2, ПЯЗ);

Листинг 3.2. Вариант с тупиковой ситуацией

ПР1:

ЖДАТЬ СООБЩЕНИЕ (ПРЗ, МЗ, ПЯ1); ПОСЛАТЬ СООБЩЕНИЕ (ПР2, M1, ПЯ2);

ПР2:

ЖДАТЬ СООБЩЕНИЕ (ПР1, M1, ПЯ2): ПОСЛАТЬ СООБЩЕНИЕ (ПРЗ, М2, ПЯЗ):

ПРЗ:

ЖДАТЬ СООБЩЕНИЕ (ПР2, М2, ПЯЗ): ПОСЛАТЬ СООБЩЕНИЕ (ПР1, МЗ, ПЯ1);

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

Пример тупика на ресурсах типа CR и SR

Пусть некоторый процесс ПР1 должен обменяться сообщениями с процессом ПР2 и каждый из них запрашивает некоторый ресурс R, причем ПР1 требует три единицы этого ресурса для своей работы, а ПР2 – две единицы и только на время обработки сообщения. Всего же имеются только четыре единицы ресурса R. Запрос ресурса можно реализовать через соответствующий монитор с процедурами REQUEST (R, N) – запрос N единиц ресурса R и RELEASE (R, N) – освобождение, возврат N единиц ресурса R. Обмен сообщениями будем осуществлять через почтовый ящик MB. Фрагменты программ ПР1 и ПР2 приведены в листинге. 3.3.

151

Листинг 3.3. Пример тупика на CR- и SR-pecypcax

ПР1: REQUEST (R, З);

SEND_MESSAGE (ПР2, сообщение, MB); WAIT_ANSWER (ответ, MB);

RELEASE (R, 3);

----------------------------------------------------------------------

ПР2: WAIT_MESSAGE (ПР1, сообщение, MB); REQUEST (R, 2;

ОБРАБОТКА СООБЩЕНИЯ; RELEASE (R, 2); SEND_ANSWER (ответ, MB);

Эти два процесса всегда будут попадать в тупик. Процесс ПР2, если будет выполняться первым, сначала ожидает сообщения от процесса ПР1, после чего будет заблокирован при запросе ресурса R, часть которого будет уже отдана ПР1. Процесс ПР1, завладев частью ресурса R, будет заблокирован на ожидании ответа от ПР2, которого никогда не получит, так как для этого ПР2 нужно получить ресурс R, находящийся в распоряжении ПР1. Тупика можно избежать лишь при условии, что на время ожидания ответа от ПР2 процесс ПР1 будет отдавать хотя бы одну единицу ресурса R, которыми он сейчас владеет. В данном примере, как и в предыдущем, причиной тупика являются ошибки программирования.

Пример тупика на ресурсах типа SR

Предположим, что существуют два процесса ПР1 и ПР2, разделяющих два ресурса типа SR: R1 и R2. Пусть взаимное исключение доступов к этим ресурсам реализуется с помощью семафоров S1 и S2 соответственно. Процессы ПР1 и ПР2 обращаются к ресурсам в порядке, проиллюстрированном на рис. 3.14. Здесь несущественные (с точки зрения обращения к ресурсам) детали опущены. Считаем, что оба семафора первоначально установлены в единицу. Пространство возможных вычислений приведено на рис. 3.15.

152

Процесс ПP1

Процесс ПP2

1:

P(S2);

5:

P(S1);

2:

P(S1);

6:

P(S2);

3:

V(S1);

7:

V(S1);

4:

V(S2);

8:

V(S2);

Рис. 3.14. Пример последовательности операторов для двух процессов, ко-

торые могут привести к тупиковой ситуации

 

 

ПР2

 

 

 

Т1

 

8

 

 

 

 

 

 

 

 

 

7

 

 

 

 

 

A

 

 

 

 

 

6

 

Y

 

 

 

 

 

C

 

 

 

D

X

 

 

 

 

 

 

 

 

 

 

 

5

 

B

 

 

 

 

 

 

 

 

1

 

2

3

4

ПР1

Рис. 3.15. Пространство состояний системы двух параллельных

 

конкурирующих процессов

 

 

 

Горизонтальная ось задает выполнение процесса ПР1, вертикальная – ПР2. Вертикальные линии, пронумерованные от 1 до 4, соответствуют операторам 1-4 процесса ПР1. Аналогично горизонтальные линии, пронумерованные от 5 до 8, соответствуют операторам 5-8 программы ПР2. Точка на плоскости определяет состояние вычислений в некоторый момент времени. Так, точка А соответствует ситуации, при которой ПР1 начал исполнение, но не достиг оператора 1, а ПР2 выполнил оператор 6, но не дошел до оператора 7. По мере выполнения точка будет двигаться го-

153

ризонтально вправо, если исполняется ПР1, и вертикально вверх, если исполняется ПР2.

Интервалы исполнения, во время которых ресурсы R1 и R2 используются каждым процессом, показаны с помощью фигурных скобок. Линии 1-8 делят пространство вычислений на 25 прямоугольников, каждый из которых задает состояние вычислений. Закрашенные серым цветом состояния являются недостижимыми из-за взаимного исключения ПР1 и ПР2 при доступе к ресурсам R1 и R2.

Рассмотрим последовательность исполнения 1-2-5-3-6-4-7-8, представленную траекторией Т1. Когда процесс ПР2 запрашивает ресурс R1 (оператор 5), ресурс недоступен (оператор выполнен, семафор закрыт). Поэтому процесс ПР2 заблокирован в точке В. Как только процесс ПР1 достигнет оператора 3, процесс ПР2 деблокируется по ресурсу R1. Аналогично в точке С процесс ПР2 будет заблокирован при попытке доступа к ресурсу R2 (оператор 6). Как только процесс ПР1 достигнет оператора 4, процесс ПР2 деблокируется по ресурсу R2.

Если же, например, выполняется последовательность 1-5-2-6, то процесс ПР1 заблокируется в точке Х при выполнении оператора 2, а процесс ПР2 заблокируется в точке Y при выполнении оператора 6. При этом процесс ПР1 ждет, когда процесс ПР2 выполнит оператор 7, а ПР2 ждет, когда ПР1 выполнит оператор 4. Оба процесса будут находиться в тупике, ни ПР1, ни ПР2 не могут закончить выполнение. При этом все ресурсы, которые получили ПР1 и ПР2, становятся недоступными для других процессов, что резко снижает возможности вычислительной системы по обслуживанию их. Отметим одно очень важное обстоятельство: тупик будет неизбежным, если вычисления зашли в прямоугольник D, являющийся критическим состоянием.

Для того чтобы возник тупик, необходимо, чтобы одновременно выполнялись четыре условия:

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

2)ожидания, при котором процесс, запросивший ресурс, ждет до тех пор, пока запрос не будет удовлетворен, при этом удерживая ранее полученные ресурсы;

3)отсутствия перераспределения, при котором ресурсы нельзя отобрать

упроцесса, если они ему уже выделены;

4)кругового ожидания, при котором существует замкнутая цепь процессов, каждый из которых ждет ресурс, удерживаемый его предшественником в этой цепи.

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

154

4.3. Методы борьбы с тупиками

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

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

предотвращение тупика; обход тупика;

распознавание тупика с последующим восстановлением.

4.3.1. Предотвращение тупиков

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

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

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

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

155

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

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

Условие кругового ожидания можно исключить, предотвращая образование цепи запросов. Это можно обеспечить с помощью принципа иерархического выделения ресурсов. Все ресурсы образуют некоторую иерархию. Процесс, затребовавший ресурс на одном уровне, может затем потребовать ресурсы только на более высоком уровне. Он может освободить ресурсы на данном уровне только после освобождения всех ресурсов на всех более высоких уровнях. После того как процесс получил, а потом освободил ресурсы данного уровня, он может запросить ресурсы на том же самом уровне. Пусть имеются процессы ПР1 и ПР2, которые могут иметь доступ к ресурсам R1 и R2, причем R2 находится на более высоком уровне иерархии. Если ПР1 захватил R1, то ПР2 не может захватить R2, так как доступ к нему проходит через доступ к R1, который уже захвачен ПР1. Таким образом, создание замкнутой цепи исключается. Иерархическое выделение ресурсов часто не дает никакого выигрыша, если порядок использования ресурсов, определенный в описании процессов, отличается от порядка уровней иерархии. В этом случае ресурсы будут использоваться крайне неэффективно.

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

4.3.2. Обход тупиков

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

Рассмотрим следующий пример. Пусть имеется система из трех вычислительных процессов, которые потребляют некоторый ресурс R типа SR,