Операционные системы
Самостоятельная работа №3
Исследование метода взаимодействия процессов с помощью очередей сообщений
Цель работы: изучение методов взаимодействия процессов с помощью очередей сообщений.
Общие сведения
Обмен сообщениями между процессами на основе буфера обладает рядом недостатков, а именно:
- ограничение размера буфера на количество сообщений, помещаемых в буфер;
- сообщения переписываются в буфер и читаются из буфера, таким образом времена записи и чтения определяются типом (размером) сообщения и могут быть большими.
Поэтому в ряде операционных сред существует другое средство обмена сообщениями, которое называется очередью сообщений. В действительности только очередью сообщений такое средство не ограничивается, а представляет собой целый объект, включающий, кроме очереди сообщений, еще и средства синхронизации записи и чтения.
В качестве последних выступают очередь процессов, пославших сообщение, и очередь процессов, ждущих сообщение.
Дадим словесное описание методов записи и чтения сообщения, а затем опишем данное средство обмена сообщениями как объект операционной среды.
Запись сообщения включает в себя следующие действия:
- включение указателя на сообщения в очередь, (обратим внимание, что именно указатель помещается в очередь, а не само сообщение, что существенно повышает скорость обмена);
- включение процесса, пославшего сообщения в очередь, тем самым процесс, пославший сообщение блокируется до момента чтения сообщения другим процессом;
- активизация процесса, ждущего сообщения, если таковой имеется.
Чтение сообщения включает в себя следующие действия:
- если сообщения отсутствуют, то блокировка процесса путем постановки его в очередь;
- если сообщение есть, то чтение сообщения и
- активизация процесса, пославшего сообщение.
Таким образом, процесс, пославший сообшение, возобновит свое выполнение только после того как его сообщение будет прочитано другим процессом.
Схематично взаимодействие процессов для случаев, когда обращение одного процесса к примитиву записи сообщения происходит раньше обращения другого процесса к примитиву чтения, и наоборот, представлены на рисунках.
Процесс 1 Процесс 2 ┌──────┴──────┐ │ │ запись │ │ └──────┬──────┘ │ │ожидание │ ┌──────┴──────┐ ┌───────┴───────┐ │возобновление│ │ чтение │ └──────┬──────┘----------------------└───────┬───────┘ Рис.1. Процесс 1 подошел к примитиву записи раньше, чем процесс 2 подошел к примитиву чтения. Процесс 2 Процесс 2 │ ┌──────┴──────┐ │ │начало чтения│ │ └──────┬──────┘ │ │ожидание ┌───────┴───────┐ ┌──────┴──────┐ │ запись │ │конец чтения│ └───────┬───────┘----------------------└──────┬──────┘ Рис.2. Процесс 1 подошел к примитиву записи позже, чем процесс 2 подошел к примитиву чтения.
Средство обмена сообщениями, удовлетворяющее приведенному выше описанию, может быть предствлено следующим образом:
ТPostBox = Object MessageList : TMessageList;{очередь указателей на сообщения} SendProcList : TList;{очередь процессов, пославших сообщения} WaitProcList : TList; {очередь процессов. ждущих сообщение} Constructor Init; Destructor Done; Virtual; Procedure PutMsg(M : Pointer); {послать сообщение} Function GetMsg : Pointer; {принять сообщение} End {TPostBox}.
Очередь указателей на сообщения по своим методам очень похожа на очередь процессов за исключением того, что оперирует с типом данных Pointer, а не с типом данных Процесс.
Constructor TPostBox.Init; Begin MessageList.Init; SendProcList.Init; WaitProcList.Init; End {TPostBox.Init}; Destructor TPostBox.Done; Begin MessageList.Done; SendProcList.Done; WaitProcList.Done; End {TPostBox.Done}; Procedure TPostBox.PutMsg(M : Pointer); Var Предыдущий : Процесс; Begin Запретить_прерывания; MessageList.Insert(M); Предыдущий := Текущий; SendProcList.Insert(Предыдущий); If WaitProcList.Первый <> NIL Then Begin Текущий := WaitProcList.Первый; WaitProcList.Remove(Текущий); End Else Begin Текущий := ReadyList.Первый; ReadyList.Remove(Текущий); End {If}; Передать_управление(Предыдущий, Текущий); Разрешить_прерывания; End {TPostBox.PutMsg}; Function TPostBox.GetMsg : Pointer; Var M : Pointer; S : Процесс; Предыдущий : Процесс; Begin Запретить_прерывания; If MessageList.Первый = NIL Then Begin Предыдущий := Текущий; WaitProcList.Insert(Предыдущий); Текущий := ReadyList.Первый; ReadyList.Remove(Текущий); Передать_управление(Предыдущий, Текущий); Запретить_прерывания; End {If}; M := MessageList.Первый; MessageList.Remove(M); GetMsg := M; S := SendProcList.Первый; SendProcList.Remove(S); ReadyList.Insert(S); Разрешить_прерывания; End {TPostBox.GetMsg}.
Представленный объект лишь моделирует в среде MS DOS работу очередей сообщений, реализованных в современных операционных системах, однако дает представление о путях решения задачи синхронизации записи и чтения сообщений разными процессами.
Задание
- Реализовать объект TPostBox средствами языка Pascal.
- Прокомментировать каждую строчку объекта TPostBox.
- Написать демонстрационную программу, иллюстрирующую функционирование объекта TPostBox.