Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
VSOS_2014.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.9 Mб
Скачать
    1. Разделяемая память. Проблема производителя и потребителя

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

Для того, чтобы проиллюстрировать концепцию взаимодействия процессов с использованием разделяемой памяти, рассмотрим так называемую проблему производителя и потребителяproducer-consumer»), также известную как проблема ограниченного буфера. Процесс-производитель производит информацию, которую обрабатывает процесс-потребитель. Например, программа вывода на печать производит последовательность символов, которые потребляются драйвером принтера, или компилятор производит ассемблерный код, который затем потребляется ассемблером.

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

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

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

Проиллюстрируем второй подход. Например, процесс-производитель и процесс-потребитель могут использовать следующие общие переменные:

var n; [количество элементов буфера]

type item.= ...; [тип элементов буфера]

var buffer: array[0..n - 1] of item;

in,out: 0..n-1;

где n - количество адресуемых элементов буфера, item имя типа элемента буфера, in, out - указатели, характеризующие заполненность буфера. Начальное значение переменных in и out равно нулю.

Очевидно, что буфер пуст, если выполняется условие in = out. Буфер будет полностью заполнен, если (in + 1)mod n = out.

Приведем примерную схему работы программ производителя и потребителя. Обозначим через no-op отсутствие действий. Предположим, что очередной элемент данных формируется процессом-производителем в локальной для него переменной nextProduced типа item. Тогда схема работы производителя будет выглядеть следующим образом:

repeat

........

[формируется очередной элемент в nextp]

........

while (in+1) mod n = out do no-op;

buffer [in]:= nextProduced;

in:=(in+1) mod n;

until false ;

Если процесс-потребитель считывает очередную порцию информации в локальную переменную nextConsumed типа item, то схема его работы будет выглядеть следующим образом:

repeat

while in = out do no-op

nextConsumed : = buffer [out];

out: = (out+1) mod n;

......

[потребляется очередной элемент из nextc]

......

until false;

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