Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

СПО

.pdf
Скачиваний:
41
Добавлен:
31.05.2015
Размер:
2.9 Mб
Скачать

Последняя модификация алгоритма планирования W2K заключается в том, что когда окно становится окном переднего плана, все его потоки получают более длительные кванты времени (величина прибавки хранится в системном реестре).

3.8. Взаимоисключения

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

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

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

2.Процессы косвенно осведомлены о наличии друг друга (например, процессы одного задания). Эти процессы не обязательно должны быть осведомлены о наличии друг друга с точностью до идентификатора процесса, однако они разделяют доступ к некоторому объекту, например буферу ввода-вывода,

кфайлу или БД. Такие процессы демонстрируют сотрудничество при разделении общего объекта.

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

работы. Эти процессы также демонстрируют сотрудничество при работе.

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

Взаимоисключение необходимо только в том случае, ко-

гда процессы обращаются к общим данным.

Если они выполняют операции, не приводящие к конфликтным ситуациям, они должны работать параллельно.

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

Если же это невозможно, процесс должен ожидать освобо-

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

Рис. 11. Поведение процессов в критической области

Требования к критическому участку:

-в любой момент времени только один процесс может находиться внутри критического участка;

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

-ни один процесс не должен ждать бесконечно долго входа в критический участок.

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

shared int ready[2] = {0, 0}; shared int turn;

while (some condition)&&

{

ready [i] = 1; turn =1- i;

while (ready [1-i]&& turn == 1-i); critical section ready [i] = 0;

remainder section

}

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

Для трех или более процессов разработан так называемый «алгоритм булочной» (bakery algorithm). Основная его идея выглядит так. Каждый вновь прибывающий клиент (он же процесс) получает «талончик» на обслуживание с номером. Клиент с наименьшим номером на «талончике» обслуживается следующим. К сожалению, из-за специфики операции вычисления следующего номера алгоритм булочной не гарантирует, что у всех процессов будут «талончики» с разными номерами. В случае равенства номеров на «талончиках» у двух или более клиентов первым обслуживается клиент с меньшим значением имени (имена можно сравнивать в лексикографическом порядке).

Разделяемые структуры данных для алгоритма - это два массива:

shared enum {false, true} choosing[n]; shared int number[n];

Изначально элементы этих массивов инициируются значениями false и 0 соответственно. Введем следующие обозначения:

(a,b) < (c,d), если а < с или если а == с и b < d

max(a0, al,…,an) - это число k такое, что k >= ai для всех i

= 0, ...,n.

Структура процесса Pi для алгоритма булочной приведена ниже

while (some condition):

{

choosing[i] = true;

number[i] = max (number[0],number[n-1]) + 1; choosing[i] = false;

for(j = 0; j<n; j++)

{

while (choosing[i]);

while (number[j] != 0 && (number[j],j) < (number[i],i));

}

critical section

number[i ] = 0; remainder section

}

5.5. Семафоры

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

Механизм взаимоисключения может быть реализован с помощью семафоров: двоичных и считающих.

С семафором связаны инициализация и две операции: P(s) - закрытие,

V(s) - открытие.

Двоичный семафор имеет два состояния - 0 и 1. Закрытый семафор находится в состоянии 0, открытый - в состоянии

1.

При инициализации семафора определяется его начальное состояние:

ИнициализацияСемафора(s, 1); или ИнициализацияСемафора(s, 0); Операция P(s):

if s = 1

then s := 0 { закрыть семафор }

else блокировать обратившийся процесс по s; установить на выполнение готовый процесс;

Операция V(s):

if список процессов, ожидающих s, не пуст then деблокировать процесс, ожидающий S else s := 1; { открыть семафор }

Критический участок окаймляется операциями P(s) и V(s). Таким образом, двоичный семафор обеспечивает логику работы с событием (Event).

Считающие семафоры полезны при выделении одиночного ресурса из общего пула.

При инициализации в s заносят количественный показатель объема ресурсов пула. P(s) вызывает уменьшение счетчика ресурса на единицу, а V(s) - увеличение счетчика на единицу, т.е.

операция P(s): if s > 0

then s := s - 1

else ожидать на s;

операция V(s):

if список процессов, ожидающих s не пуст then разрешить одному процессу работать else s := s + 1;

Считающие семафоры реализованы в программном интерфейсе Windows. Их использование аналогично использованию событий и критических секций, т.е. семафор может быть в отмеченном или неотмеченном состоянии.

5.6. Тупики

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

Пример. В операционных системах тупики в большинстве случаев возникают в результате обычной конкуренции за об-

ладание выделяемыми или закрепляемыми ресурсами (т.е. ре-

сурсами, которые в каждый момент времени отводятся только одному пользователю и которые поэтому иногда называются ресурсами последовательного использования).

Пусть Процесс1 удерживает Ресурс1 и ожидает освобождения Ресурса2. Процесс2 удерживает Ресурс2 и ожидает освобождения Ресурса1. Каждый процесс ждет, чтобы другой процесс освободил нужный ему ресурс, причем каждый не освобождает свой ресурс до тех пор, пока другой не освободит свой ресурс и т.д. Такое состояние кругового ожидания характерно для систем в тупиковом состоянии (рис. 12).

Рис. 12. Пример тупиковой ситуации

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

Условие взаимоисключения: процессы требуют предос-

тавления им права монопольного управления ресурсами, которые им выделяются.

Условие ожидания ресурсов: процессы удерживают ре-

сурсы, уже выделенные им, ожидая выделения дополнительных ресурсов.

Условие неперераспределяемости: ресурсы нельзя ото-

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

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

В исследованиях по проблеме тупиков можно выделить следующие основные направления:

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

обход тупиков;

обнаружение тупиков;

восстановление после тупиков.

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

Предлагается стратегия, включающая три принципа:

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

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

введение линейной упорядоченности по типам ресур-

сов.

Все элементы этой стратегии имеют свои недостатки.

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

Обнаружение тупика – это установление факта, что возникла тупиковая ситуация, и определение процессов и ресурсов, вовлеченных в тупиковую ситуацию.

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

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

Самый целесообразный способ – это эффективный механизм приостановки/возобновления процесса.

Другой способ – создание контрольных точек (дампов памяти) и перезапуск.

4. УПРАВЛЕНИЕ ПАМЯТЬЮ

4.1. Функции ОС по управлению памятью

Под памятью (memory) подразумевается оперативная память компьютера. В однозадачных операционных системах основная память разделяется на две части. Одна часть – для операционной системы (резидентный монитор, ядро), а вторая

– для выполняющейся в текущий момент времени программы. В многопрограммных ОС «пользовательская» часть памяти – важнейший ресурс вычислительной системы – должна быть распределена для размещения нескольких процессов, в том числе и процессов ОС. Эта задача распределения выполняется операционной системой динамически специальной подсистемой управления памятью (memory management). Эффективное управление памятью жизненно важно для многозадачных систем. Если в памяти будет находиться небольшое число процессов, то значительную часть времени процессы будут находиться в состоянии ожидания ввода-вывода и загрузка процессора низкой.

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

Функциями ОС по управлению памятью в мультипрограммных системах являются:

отслеживание (учет) свободной и занятой памяти;

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

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

полное или частичное вытеснение кодов и данных процессов из ОП на диск, когда размеры ОП недостаточны для размещения всех процессов, и возвращение их в ОП;