Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
os4.doc
Скачиваний:
0
Добавлен:
20.06.2023
Размер:
403.46 Кб
Скачать

Раздел 4. Взаимодействие процессов

4.1. Примитивы синхронизации процессов

4.1.1. Простейшие примитивы, не учтенные в классификации

Это примитивы “Приостановить_Процесс” и “Возобновить_Процесс”. Для описания этих примитивов вспомним 2-й вывод предыдущего параграфа об очередях.

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

void Приостановить_Процесс(TProcess* P)

{

ПРОЛОГ;

КОНТРОЛЬ;

<

Вывести процесс Р из очереди, в которой он находится;

Ввести процесс Р в очередь приостановленных процессов;

>

ПЕРЕНАЗНАЧИТЬ_ПРОЦЕССОР;

}

void Возобновить_Процесс(TProcess* P)

{

ПРОЛОГ;

КОНТРОЛЬ;

<

Вывести процесс Р из очереди приостановленных процессов;

Ввести процесс Р в очередь готовых процессов;

>

ПЕРЕНАЗНАЧИТЬ_ПРОЦЕССОР;

}

Замечания

  1. Вид этих примитивов реализует общую идею приостановки/возобновления, которая может быть реализована по-разному.

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

  1. В некоторых ОС при приостановке процесса Р необходимо приостанавливать и всех его потомков. Другой вариант состоит в том, что только своих потомков и может приостанавливать процесс. Все эти ограничения учитываются обработкой полей дескриптора процесса.

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

  1. Приведенные примитивы можно рассматривать как первую попытку синхронизации действий нескольких процессов.

4.1.2. Примитивы временной синхронизации

При временной синхронизации ВРЕМЯ выступает в качестве меры длительности явлений.

Забегая вперед, скажем, что в других случаях не важна абсолютная длительность явлений, а важны только соотношения РАНЬШЕ/ПОЗЖЕ.

Проблемы временной синхронизации решаются с помощью примитива

Задержать_Процесс(TProcess* P, int T);

Здесь Т рассматривается как целое число, т. к. время в машине измеряется количеством «тиков» - интервалов времени между прерываниями от таймера.

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

… …

Delay(T); for (k = 0; k < N; k++) {}

… …

Вопрос состоит только в выборе подходящего значения N.

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

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

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

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

Совершенно понятно, как поставить процесс в очередь. Встает вопрос, когда его из этой очереди извлечь и перевести в очередь готовых процессов.

Если процесс ставится в очередь в текущий момент времени Тт, и время, на которое он ставится в очередь, равно Т, то активизировать его надо в текущий момент времени Та = Тн + Т.

На схеме Т = 7.

В ядре информацией о текущем времени владеет диспетчер, т.к. это обработчик прерываний от таймера - счетчика времени.

Диспетчер подсчитывает время в виде «тиков», поэтому извлекать процессы из очереди задержанных на время процессов лучше всего диспетчеру. Делать это надо тогда, когда текущее время совпадет с временем активизации процесса.

Время активизации процесса вычисляется по формуле Та = Тт+Т в момент постановки в очередь задержанных на время процессов и записывается в специальное поле в дескрипторе процесса.

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

Существует аналогия с уничтожением процессов. Примитив Уничтожить_Процесс переводит процесс в очередь уничтожаемых процессов, а диспетчер на каждом такте очищает эту очередь.

Здесь: примитив Задержать_Процесс переводит процесс в очередь задержанных процессов, а диспетчер на каждом такте эту очередь анализирует и активизирует процессы, для которых совпало текущее время с временем активизации.

Таким образом, примитивов задержки и активизации будет иметь следующий вид:

void Задержать_Процесс(TProcess* P, int T)

{

ПРОЛОГ;

КОНТРОЛЬ;

<

Вывести процесс Р из очереди, в которой он находится;

Ввести процесс Р в очередь задержанных на время процессов;

Установить поле дескриптора процесса Р в соответствие с

формулой Та = Тт + Т;

>

ПЕРЕНАЗНАЧИТЬ_ПРОЦЕССОР;

}

void АКТИВИЗАЦИЯ_ЗАДЕРЖАННЫХ_НА_ВРЕМЯ_ПРОЦЕССОВ()

{

Для всех процессов из очереди задержанных делать следующее:

Если Время активизации процесса равно текущему времени, то

1) Вывести процесс из очереди задержанных на время процессов;

2) Ввести процесс в очередь готовых процессов;

}

Процедуру АКТИВИЗАЦИЯ_ЗАДЕРЖАННЫХ_НА_ВРЕМЯ_ПРОЦЕССОВ необходимо поместить в Диспетчер:

void interrupt Dispatcher()

{

АКТИВИЗАЦИЯ_ЗАДЕРЖАННЫХ_НА_ВРЕМЯ_ПРОЦЕССОВ;

ОЧИСТИТЬ_ОЧЕРЕДЬ_УНИЧТОЖАЕМЫХ_ПРОЦЕССОВ;

ПЕРЕНАЗНАЧИТЬ_ПРОЦЕССОР;

}

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

Соседние файлы в предмете Операционные системы