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

3.10.2. Почтовый ящик с очередью сообщений

Вопрос (

Недостаток буфера, заключающийся в фиксированном его размере, устраняется путем использования динамического объекта - очереди сообщений.

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

)Вопрос

В качестве средств синхронизации записи и чтения по-прежнему будем использовать очереди процессов.

Опишем объект, удовлетворяющий приведенной выше спецификации, и назовем его почтовым ящиком.

Type

TPostBox = ^TPostBox;

TPostBox = Object

TList : PList; {очередь процессов, пославших сообщение}

RList : PList; {очередь процессов, ждущих сообщения}

MList : PList; {очередь указателей на сообщения}

Constructor Init;

Destructor Done;

Procedure PutMsg(M : Pointer);

Procedure GetMsg(Var M : Pointer);

End {TPostBox};

Замечания

  1. Схема использования почтового ящика в прикладной программе аналогична схеме использования буфера.

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

  1. Процессы, естественно, знают тип сообщений как тип данных.

Сonstructor TPostBox.Init;

Begin

RList := New(PList, Init);

TList := New(PList, Init);

MList := New(PList, Init);

End {TPOstBox.Init};

Destructor TPostBox.Done;

Begin

Dispose(RList, Done);

Dispose(TList, Done);

Dispose(MList, Done);

End {TPostBox.Done};

Procedure TPostBox.PutMsg(M : Pointer);

Begin

Запрет прерываний;

MList^.Insert(M);

TList^.Insert(Текущий процесс);

If RList не пуста Then

RList^.Remove(Первый процесс)

Else

Очередь_готовых.Remove(Первый процесс);

Передать управление(Текущий процесс, Первый процесс);

Разрешение прерываний;

End {TPostBox.PutMsg};

Procedure TPostBox.GetMsg(Var M : Pointer);

Begin

Запрещение прерываний;

If MList пуста Then Begin

RList^.Insert(Текущий процесс); {ждем записи}

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

End {If};

MList^.Remove(Первое сообщение);

M := Первое сообщение;

Tlist^.Remove(Первый процесс);

Очередь_готовых.Insert(Текущий процесс);

Передать управление(Текущий процесс, Первый процесс);

Разрешение прерываний;

End {TPostBox.GetMsg};

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

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

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

Такой способ обмена сообщениями, когда передающий процесс блокируется, пока его сообщение не будет принято принимающим процессом, называется РАНДЕВУ. Этот механизм реализован в языке АДА.

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