Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OS_REDACTED_БИЛЕТЫ.docx
Скачиваний:
9
Добавлен:
01.04.2022
Размер:
1.15 Mб
Скачать
  1. Решите задачу производителя/потребителя через алгоритм Петерсона

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

#define FALSE 0

#define TRUE 1

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

int turn; /* чья очередь? */

int interested[N]; /* все исходные значения равны 0 (FALSE) */

void enter_region(int process); /* process имеет значение 0 или 1 */

{

int other; /* номер другого процесса */

other = 1 − process; /* противостоящий процесс */

interested[process] = TRUE; /* демонстрация заинтересованности */

turn = process; /* установка флажка */

while (turn == process && interested[other] == TRUE)/* цикл без инструкции */; }

void leave_region(int process)

/* процесс, покидающий критическую область */

{

interested[process] = FALSE; /* признак выхода из критической области */ }

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

АЛГОРИТМ. Изначально ни один из процессов не находится в критической области. Затем процесс 0 вызывает функцию enter_region. Он демонстрирует свою заинтересованность, устанавливая свой элемент массива и присваивая переменной turn значение 0. Поскольку процесс 1 заинтересованности во входе в критическую область не проявил, функция enter_region тотчас же возвращает управление. Теперь, если процесс 1 вызовет функцию enter_region, он зависнет до тех пор, пока interested[0] не получит значение FALSE, а это произойдет только в том случае, если процесс 0 вызовет функцию leave_region, чтобы выйти из критической области. Теперь рассмотрим случай, когда оба процесса практически одновременно вызывают функцию enter_region. Оба они будут сохранять свой номер процесса в переменной turn. В расчет берется последнее сохранение, поскольку первое будет переписано и утрачено. Предположим, что процесс 1 сохранил свой номер последним и turn имеет значение 1. Когда оба процесса доберутся до оператора while, процесс 0 не выполнит его ни одного раза и войдет в свою критическую область. Процесс 1 войдет в цикл и не будет входить в свою критическую область до тех пор, пока процесс 0 не выйдет из своей критической области.

  1. Решите задачу производителя/потребителя через семафоры и мьютексы

С помощью семафоров решается проблема утраченных активизаций. Чтобы заставить их корректно работать, очень важно, чтобы их реализация предусматривала неделимый режим работы. Вполне естественно было бы реализовать операции up и down в виде системных вызовов, чтобы операционная система на время тестирования семафора, обновления его значения и приостановки процесса при необходимости кратковременно запрещала все прерывания. Поскольку все эти действия занимают только несколько команд, запрет на прерывания не причинит никакого вреда. Если используются несколько центральных процессоров, каждый семафор должен быть защищен переменной lock, а для гарантии того, что семафор в отдельно взятый момент времени задействуется только одним центральным процессором, используется команда TSL или XCHG. Нужно усвоить, что использование TSL или XCHG для предупреждения одновременного доступа к семафору нескольких центральных процессоров в корне отличается от режима активного ожидания производителем или потребителем момента опустошения или наполнения буфера. Операция работы с семафором займет лишь несколько микросекунд, а ожидание производителя или потребителя может быть сколь угодно долгим. В этом решении используются три семафора: один из них называется full и предназначен для подсчета количества заполненных мест в буфере, другой называется empty и предназначен для подсчета количества пустых мест в буфере, третий называется mutex, он предотвращает одновременный доступ к буферу производителя и потребителя. Семафор full изначально равен 0, семафор empty изначально равен количеству мест в буфере, семафор mutex изначально равен 1. Семафоры, инициализированные значением 1 и используемые двумя или более процессами для исключения их одновременного нахождения в своих критических областях, называются двоичными семафорами. Взаимное исключение гарантируется в том случае, если каждый процесс совершает операцию down непосредственно перед входом в свою критическую область и операцию up сразу же после выхода из нее. В системе, использующей семафоры, естественным способом скрыть прерывания станет использование семафора с исходным нулевым значением, связанным с каждым устройством ввода-вывода. Сразу же после запуска устройства ввода-вывода управляющий процесс выполняет операцию down в отношении связанного с этим устройством семафора, при этом немедленно переходя в состояние заблокированности. Затем при поступлении прерывания его обработчик выполняет операцию up в отношении связанного с устройством семафора, которая переводит соответствующий процесс в состояние готовности к продолжению выполнения. В этой модели шаг 5 из табл. 2.2 состоит из выполнения операции up над семафором устройства, с тем чтобы на шаге 6 планировщик мог запустить программу, управляющую устройством. Разумеется, если к этому моменту будут готовы 160 Глава 2. Процессы и потоки к выполнению сразу несколько процессов, планировщик может выбрать следующим для выполнения более важный процесс. Позже в этой главе мы еще рассмотрим некоторые алгоритмы, используемые для работы планировщика. В примере, приведенном в листинге 2.6, семафоры используются двумя различными способами. Различия этих способов настолько важны, что требуют дополнительного разъяснения. Семафор mutex используется для организации взаимного исключения. Его предназначение — гарантировать, что в каждый отдельно взятый момент времени к буферу и соответствующим переменным имеет доступ по чтению или записи только один процесс. Организуемое взаимное исключение призвано предотвратить хаос. В следующем разделе мы изучим взаимное исключение и способы его достижения.

#define N 100 /* Количество мест в буфере */

typedef int semaphore; /* Семафоры — это специальная разновидность целочисленной переменной */

semaphore mutex = 1; /* управляет доступом к критической области */

emaphore empty = N; /* подсчитывает пустые места в буфере */

semaphore full = 0; /* подсчитывает занятые места в буфере */

void producer(void)

{

int item;

while (TRUE) { /* TRUE — константа, равная 1 */

item = produce_item( ); /* генерация чего-то для помещения в буфер */

down(&empty); /* уменьшение счетчика пустых мест */

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

insert_item(item); /* помещение новой записи в буфер */

up(&mutex); /* покинуть критическую область */

up(&full); /* инкремент счетчика занятых мест */

} }

void consumer(void)

{

int item; while (TRUE) { /* бесконечный цикл */

down(&full); /* уменьшение счетчика занятых мест */

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

item = remove_item( ); /* извлечение записи из буфера */

up(&mutex); /* выход из критической области */

up(&empty); /* увеличение счетчика пустых мест */

consume_item(item); /* работа с записью */

} }

Другие семафоры используются для синхронизации. Семафоры full и empty нужны для гарантии наступления или ненаступления тех или иных конкретных последовательностей событий. В данном случае они гарантируют, что производитель приостановит свою работу при заполненном буфере, а потребитель приостановит свою работу, если 2.3. Взаимодействие процессов 161 этот буфер опустеет. Эти семафоры используются совсем не так, как при обеспечении взаимного исключения.