Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
NewОтветыОС_1.doc
Скачиваний:
37
Добавлен:
07.02.2015
Размер:
2.67 Mб
Скачать
  1. Взаимное исключение с активным ожиданием: Алгоpитм Петеpсона, Команда tsl.

Датский математик Деккер (Т. Dekker) первым разработал программное решение проблемы взаимного исключения, не требующее строгого чередования. В 1981 году Петерсон разработал существенно более простой алгоритм взаимного исключения.

Решение Петерсона для взаимного исключения

#define FALSE 0

#define TRUE 1

#define N 2 /* Количество процессов */

int turn; /* Чья сейчас очередь? */

int interested[N]; /*Все перемен изначал =0 (FALSE) */

void enter_region(int process); /* Процесс 0 или 1 */

{ int other; /* Номер второго процесса */

other = 1 - process; /* Противоположный процесс */

interested[process] = TRUE; /* Индикатор интереса*/

turn = process; /* Установка флага*/

while (turn = process && interested[other] = TRUE)/*Пустой оператор*/;

}

void leave_region(int process) /* process - процесс, покидающий кр обл*/

{

interested[process] = FALSE; /* Индикатор выхода из кр обл*/

}

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

Команда TSL (Test and Set Lock — проверить и заблокировать)Многие компьютеры, особенно разработанные с расчетом на несколько процессоров, имеют команду TSL RX, LOCK. в регистр RX считывается содержимое слова памяти lock, а в ячейке памяти lock сохраняется некоторое ненулевое значение. Гарантируется, что операция считывания слова и сохранения неделима - другой процесс не может обратиться к слову в памяти, пока команда не выполнена. Процессор, выполняющий команду TSL, блокирует шину памяти, чтобы остальные процессоры не могли обратиться к памяти.

Воспользуемся командой TSL. Пусть совместно используемая переменная lock управляет доступом к разделенной памяти. Если значение переменной lock = 0 – то общ память доступна, если lock ≠ 0 то в крит обл зайти нельзя.

enter_region:

TSL Reg,Lock ; Reg=lock, lock = 1

GMP Reg,#0 ; Reg=0?

JNE enter_region ; если Reg≠0, то блокир уже установлена, поэтому цикл завершается

RET ; возврат к вызыв прогр, процесс вошел в кр обл

1eave_region:

MOVE Lock,#0 ;lock=0 ,разреш дост

RET

Прежде чем попасть в кр обл, процесс вызывает процедуру enter_region, которая выполняет активное ожидание вплоть до снятия блокировки, затем она устанавл блокировку и возвращается. При выходе из кр обл процесс вызывает процедуру leave_region, помещающую 0 в переменную lock.

  1. Пpимитивы межпpоцессного взаимодействия. Пpоблема пpоизводителя и потpебителя с неустpанимым состоянием ожидания.

Примитивы межпроцессного взаимодействия

Оба решения - Петерсона и с использованием команды TSL — корректны, но они обладают одним и тем же недостатком: использованием активного ожидания. Он может иметь некоторые неожиданные последствия.

Рассмотр 2 процесса: Н- с высоким приоритетом, и L - с низким приоритетом. L-> критич. обл. (turn=1), а Н-завершение I/O, и переключается на ЦП (L в wait) и Н хочет зайти в КО. Процесс Н в сост активного ожидания, но проц L во время работ проц Н никогда не будет предоставлено процессорное время, проц L не сможет выйти из КО, и проц Н навсегда останется в цикле. Эту ситуацию иногда называют проблемой инверсии приоритета.

Примитивы межпроцес взаимод блокируют процессы в случае запрета на вход в критическую область (примен вместо циклов ожидания). Одной из простейших является пара примитивов sleep и wakeup. 1) sleep - сист запрос, в результате которого вызывающий процесс блокируется, пока его не запустит другой процесс. 2) У запроса wakeup есть параметр - процесс, который следует запустить. Также возможно наличие одного параметра у обоих запросов - адреса ячейки памяти, используемой для согласования запросов ожидания и запуска.

Проблема производителя и потребителя (проблема ограниченного буфера)

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

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

#define N 100 /* Максим кол-во эл-ов в буфере */

int. count - 0: /* Текущ кол-во эл-ов в буфере */

void producer(void)

{ Int item:

while (TRUE) { /* повторять вечно */

item = produce_item(); /* создать след-ий элем */

if (count == N) sleep(); /* если буфер полон, уйти в сост ожидания */

insert_item(item); /* поместить элем в буфер */

count = count +1; /* увелич кол-во элем в буфере */

if (count == 1) wakeup(consumer); /* был ли буфер пуст? */

} }

void consumer(void)

{ int item;

while (TRUE) { /* повторять вечно */

if (count == 0) sleep(); /* если буфер пуст, уйти в сост ожидания */

item = remove_item(); /*забрать элем из буфера */

count = count - 1: /* умен счетч элем в буфере */

if (count == N - 1) wakeup(producer); /* был ли буфер полон? */

consume_item(item); /* отправ элем на печать */

Процедуры insert_item и remove_item помещают элементы в буфер и извлекают их оттуда. Сост состязания возможно, поскольку доступ к переменной count не ограничен. Может возникнуть ситуация: 1) буфер пуст, и потребит считал значение переменной count, чтобы проверить, не равно ли оно нулю. 2) планировщик запускает производит, производитель поместил элемент в буфер и count= count+1. Производ активиз потребит с помощью вызова wakeup, но потреб не спит, и сигнал теряется. 3) производит заполнил буфер и уснул. 4) управл перешло к потребителю, он прочит старое значен count=0 и заснет. 5) произв и потреб спят

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]