Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Процессы-ресурсы - теория.doc
Скачиваний:
10
Добавлен:
20.08.2019
Размер:
894.46 Кб
Скачать

2.2.5. Параллельное программирование и мониторы

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

  • можно “забыть” воспользоваться семафором и передать управление в критическую секцию, минуя семафор, в результате чего несколько процессов могут одновременно оказаться в критической секции и получить доступ к разделяемым ресурсам, что приведет к их разрушению;

  • можно забыть освободить семафор, что заблокирует доступ к разделяемым данным всем процессам в системе и приведет к тупиковой ситуации;

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

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

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

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

  • упрощали бы решение сложных проблем параллельных вычислений;

  • упрощали бы анализ корректности программ;

  • предотвращали бы некорректное их использование.

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

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

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

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

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

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

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

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

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

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

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

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

Monitor RESOURCE_MANAGER ;

var BUSY : boolean ;

FREE : condition ;

procedure RESERVE ; {Процедура резервирования ресурса}

begin

if BUSY then

wait (FREE) ;

BUSY := true

end ;

procedure RELEASE ; {Процедура освобождения ресурса}

begin

BUSY := false ;

signal (FREE)

end ;

begin

BUSY := false ; {Инициализация монитора}

end .

Для получения в свое распоряжение ресурса процесс должен обратиться к процедуре RESERVE монитора оператором типа

RESOURCE_MANAGER.RESERVE;

а для освобождения занятого ресурса выполнить оператор

RESOURCE_MANAGER.RESERVE;

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

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

Рассмотрим решение поставленной выше задачи “производитель-потребитель” при работе с кольцевым буфером, вмещающим N записей, с помощью монитора.

Monitor BUFFER_MANAGER ;

var BUFFER : array [ 0 .. N - 1] of DATA_TYPE ;

CURRENT_RECORD : 0 .. N - 1;

CURRENT_WRITE : 0 .. N - 1;

CURRENT_READ : 0 .. N - 1;

NOT_EMPTY , NOT_FULL: condition ;

procedure WRITE_RECORD ( DATA : DATA_TYPE ) ;

{ Процедура заполнения одной записи в буфере }

begin

if CURRENT_RECORD = N then

wait (NOT_FULL) ; {Буфер заполнен - ожидание появления свободной записи}

BUFFER [CURRENT_WRITE] := DATA ;

CURRENT_RECORD := CURRENT_RECORD + 1 ;

CURRENT_WRITE := ( CURRENT_WRITE + 1 ) mod N ;

signal ( NOT_EMPTY ) ; { Уведомление о появлении записи в буфере }

end ;

procedure READ_RECORD ( var DATA : DATA_TYPE) ;

{Процедура чтения записи из очередной позиции в буфере и ее освобождение}

begin

if CURRENT_RECORD = 0 then

wait (NOT_EMPTY) ; {Буфер пуст - ожидание появления записи}

DATA := BUFFER [CURRENT_READ] ;

CURRENT_RECORD := CURRENT_RECORD - 1 ;

CURRENT_READ := ( CURRENT_READ + 1 ) mod N ;

signal ( NOT_FULL ) ; { Уведомление об удалении записи из буфера }

end ;

begin { Инициализация монитора }

CURRENT_RECORD := 0 ;

CURRENT_READ := 0 ; CURRENT_WRITE := 0 ;

end .

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

Процедура инициализации

procedure INIT;

begin

create monitor BUFFER_MANAGER ;

start(P1) ;

start(P2)

end INIT .

Процесс-производитель

process P1;

var NEW_REC : DATA_TYPE ;

begin

while true do

begin

...

produce_next_record (NEW_REC);

BUFFER_MANAGER.WRITE_RECORD (NEW_REC);

...

end

end P1 .

Процесс-потребитель

process P2;

var NEW_REC : DATA_TYPE ;

begin

while true do

begin

...

BUFFER_MANAGER.READ_RECORD (NEW_REC);

process_new_record (NEW_REC);

...

end

end P2 .

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

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

При разработке современных ОС используется объектно-ориентированный подход. Идея использования мониторов как основных структурных единиц операционной системы (или мониторной системы) хорошо вписывается в концепцию объектно-ориентированного программирования.

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

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

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