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

В каждый момент времени активна только одна процедура монитора. Буфер состоит из N сегментов.

monitor ProducerConsumer

condition full, empty;

integer count;

procedure insert(item: integer);

begin

if count = H then wait(full);

insert_item(item);

count := count+1;

if count = 1 then signal(empty)

end;

function remove: integer:

begin

if count = 0 then wait(empty);

remove = remove_item;

count := count-1:

if count = N-l then signal(full)

end;

count := 0;

end monitor;

procedure producer;

begin

while true do

begin

item = produce_item;

ProducerConsumer.insert(item)

end

end;

procedure consumer;

begin

while true do

begin

item = ProducerConsumer.remove;

consume_item(item)

end

end;

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

Недостатки мониторов: 1) мониторы должны быть элементом ЯВУ, и компилятор должен их распознавать и организовывать взаимное исключение(в Pascal, С нет мониторов).

2) мониторы и семафоры были созданы для решения задачи взаимного исключения в системе с одним или несколькими процессорами, имеющими доступ к общей памяти(N проц →1 ОЗУ). Вывод: семафоры - примитив низкого уровня, а мониторы могут использоваться только в некоторых языках программирования.

  1. Пpоблема обедающих философов и ее pешение.

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

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

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

Решение исключающее взаимоблокировку и позволяет реализовать максимально возможный параллелизм для любого числа философов. Используется массив state для отслеживан состояния философа: ест, думает, голодает. Философ может начать есть, только если ни один из его соседей не ест. Соседи философа с номером i определяются макросами LEFTn RIGHT (то есть если i = 2, то LEFT- 1 и RIGHT - 3).

Решение задачи обедающих философов

#define N 5 /* Количество философов */

#define LEFT (i+N.l)%N /*Ном лев соседа фил с ном i/

#define RIGHT (i+l)%N /* Ном прав соседа фил с ном i*/

#define THINKING 0 /* Философ размышляет */

#define HUNGRY I /* Философ пытается получ вилки */

#define EATING 2 /* Философ ест */

typedef int semaphore; /* Семафоры - особый вид целочисленных переменных */

int state[N]; /* Массив для отслеживания состояния каждого философа */

semaphore mutex - 1; /* Взаимное исключение для критических областей */

semaphore s[N]; /* Каждому философу по семафору */

void philosopherdnt i) /* i - номер философа, от 0 до N-1

{ while (TRUE) { /* Повторять до бесконечности */

Think(): /* Философ размышляет */

Take_forks(i): /* Получает две вилки или блокируется */

eat(); /* ест */

put_forks(i); /* Кладет на стол обе вилки */

} }

void take_forks(int i) /* i - номер философа, от 0 до N-1*/

{ down(&mutex); /* Вход в крит обл */

state[i] = HUNGRY: /* Фиксация наличия голодного философа */

test(i): /* Попытка получить две вилки */

up(&mutex): /* Выход из крит обл */

down(&s[i]); /* Блокировка, если вилок не досталось */

void put_forks(i) /* i - номер философа, от 0 до N-1*/

{ down(&nutex): /* Вход в крит обл */

state[i] = THINKING: /* Философ перестал есть */

test(LEFT); /* Проверить, может ли есть сосед слева */

test(RIGHT): /* Провер, может ли есть сосед справа */

up(&mutex); /* Выход из крит обл */

void test(i) /* i - номер философа, от 0 до N-1*/

{ if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING) stated ] = EATING;

up(&s[i]); } }

Обратите внимание, что каждый процесс запускает процедуру philosopher в качестве своей основной программы, но остальные процедуры take_forks, put_forks и test являются обычными процедурами, а не отдельными процессами. Демонстрир доступ нескольк проц к огран ресурс

  1. Пpоблема читателей и писателей и ее pешение. Демонстрир множеств доступ к БД. Проблема: писатель 1, читател много. Писать можно когда нет читателей.

rc-число читателей

typedef int semaphore: /* Воспользуйтесь своим воображением */

semaphore mutex =1: /* Контроль доступа к rc */

semaphore db = 1; /* Контроль доступа к БД */

int гс = 0: /* Кол-во проц, чит или желающ читать */

void reader(void)

{while (TRUE) { /* Повторять до бесконечности */

down(&mutex); /* Получ монопольн доступа к rc */

rc = rc +1: /* Одним читающим процессом больше */

if (rc == 1) down(&db): /* Если читающ проц – 1-й */

up(&mutex): /* Отказ от монопольн доступа к rc */

read_data_base();/* Доступ к данным */

down(&mutex); /* Получение монопольн дост к rc */

rc = rc -1: /* Одним читающим процессом меньше */

if (rc == 0) up(&db); /* Если чит проц - последний

up(&mutex); /* Отказ от монопольн доступа к rc */

use_data_ read();/* Вне критической области */

} }

void writer(void)

{while (TRUE) { /* Повторять до бесконечности */

think_up_data():/* Вне критической области */

down(Sdb): /* Получение монопольного доступа */

write_data_base();/* Запись данных */

up(&db); /* Отказ от монопольного доступа */

} }

Первый читатель блокир доступ к БД , а остальные только увелич счетчик читателей. Если читетель уходит то счетчик читател уменьш. Когда уходит послед читатель он снимает блокировку с БД, позволяя писателю получить доступ к БД. Если во время использ базы читателем, пришел еще один читатель, и еще один читатель то они друг другу не мешают. Но если в непрер потоке читетелей доступ к БД запросит писатель то запрос будет отклонен и писатель будет блокирован. . Запрос отклонен, т. к. пишущим процессам необходим монопольный доступ. Пока в базе есть хотя бы один активный читающий процесс, доступ остальным читателям разрешается, а они все приходят и приходят. Если, предположим, новый читающий процесс запрашивает доступ каждые 2 с, а провести в базе ему надо 5 с, то пишущий процесс никогда в базу не попадет.

Выход 1) если писатель ждет доступа к БД, новый читатель доступа не получает, а становится в очередь за писателем. Теперь писателю нужно подождать, пока БД покинут уже находящиеся в ней читатели, не пропуская пришедших после него читателей. («-» снижение производ –и)

2) сделать приоррит писат выше приорит читат, если приорит больше то отсвоб КО сразу переход к писат.

  1. Пpоблема спящего бpадобpея и ее pешение.

Демонстрир проблему массового обслуживания. В парикмахерской есть один брадобрей, его кресло и n стульев для посетителей. Если посетител нет, брадобрей сидит в своем кресле и спит. Если в парикмахерскую приходит клиент, он должен разбудить брадобрея. Если клиент приходит и видит, что брадобрей занят, он либо садится на стул (если есть место), либо уходит (если места нет). Необходимо запрограммировать брадобрея и посетителей так, чтобы избежать состояния состязания.

В решении используются 3 семафора: customers - для подсчета ожидающих посетителей, barbers - число брадобреев (0 или 1), простаивающих в ожидании клиента, и mutex - для реализации взаимного исключения. Переменная waiting предназначенная для подсчета ожидающих посетителей(копия переменной customers). Эта премен нужна , т.к. прочитать текущее значение семафора невозможно.

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

#define CHAIRS 5 /* Кол-во стульев для посетителей */

typedef int semaphore;

semaphore customers = 0: /* Кол-во ожидающих посетителей */

semaphore barbers = 0; /* Кол-во брадобреев, ждущих клиентов */

semaphore mutex = 1: /* Для взаимного исключения */

int waiting = 0; /* Ожидающие посетители */

void barber(void)

{ while (TRUE) {

down(&customers); /* Если посетителей нет. уйти в состояние ожидания */

down(&mutex); /* Запрос доступа к waiting */

waiting = waiting – 1; /* Уменьшение числа ожидающих посетителей */

up(&barbers); /* Один брадобрей готов к работе */

up(&mutex); /* Отказ от доступа к waiting */

cut hair(); /* Клиента обслуживают (вне критической области)*/

} }

void customer(void)

{down(&mutex); /* Вход в критическую область */

if (waiting < CHAIRS) /* Если свободных стульев нет. придется уйти */

waiting = waiting+1; /* Увеличение числа ожидающих посетителей */

up(Scustomers); /* При необходимости, разбудить брадобрея */

up(&mutex); /* Отказ от доступа к waiting */

down(&barbers); /* Если брадобрей занят, уйти в состояние ожидания */

get_haircut();/* Клиента усажив и обслуживают */

} else { up(&mutex); } } /* мест нет */

Приходя в парикмахерскую, посетитель выполняет процедуру customer, запрашивая доступ к mutex для входа в критическую область. Если вслед за ним появится еще один посетитель, ему не удастся что-либо сделать, пока первый посетитель не освободит доступ к mutex. Затем посетитель проверяет наличие свободных стульев, в случае неудачи освобождает доступ к mutex и уходит. Если свободный стул есть, посетитель увеличивает значение целочисленной переменной waiting. Затем он выполняет процедуру up на семафоре customers, тем самым активизируя поток брадобрея. В этот момент оба — посетитель и брадобрей — активны. Когда посетитель освобождает доступ к mutex, брадобрей захватывает его, проделывает некоторые служебные операции и начинает стричь клиента. По окончании стрижки посетитель выходит из процедуры и покидает парикмахерскую. В отличие от предыдущих программ, цикла посетителя нет, поскольку каждого посетителя стригут только один раз. Цикл брадобрея существует, брадобрей пытается найти следующего посетителя. Если ему это удается, он стрижет следующего посетителя, в противном случае брадобрей засыпает.

УПPАВЛЕНИЕ ПАМЯТЬЮ

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