Очереди воплощают модель взаимодействия процессов "много отправителей - один получатель". Эту модель часто называют почтовым ящиком (mailbox) из-за сходства с почтовым ящиком, висящим на дверях каждой квартиры.
Процесс-получатель является владельцем очереди, он создает очередь, а остальные процессы получают к ней доступ, "открывая" ее. Очередь обычно имеет внешнее имя. Передача данных в очереди происходит всегда сообщениями, причем каждое сообщение имеет заголовок и тело. Заголовок всегда имеет фиксированный для данной системы формат. В него обязательно входит длина сообщения, а другая информация зависит от спецификаций конкретной системы: это может быть приоритет сообщения, тип сообщения, идентификатор процесса, пославшего сообщение и т.п. Тело сообщения интерпретируется по правилам, устанавливаемым самими процессами - отправителем и получателем. Заголовок и тело представляют собой существенно разные структуры данных и располагаются в разных местах в памяти. Собственно очередь (чаще всего - линейный список) ОС составляет из заголовков сообщений. В элементы очереди включаются указатели на тела сообщений, располагающиеся в памяти системы или процессов (об этом - ниже).
Как правило, возможности процесса-получателя сообщений не ограничиваются чтением по дисциплине FIFO, ему предоставляется более богатый выбор дисциплин: LIFO, по приоритету, по типам, по идентификаторам отправителя и т.п. В распоряжении владельца имеются также средства определения размера очереди, а возможно, и просмотра очереди - неразрушающего чтения из нее. В распоряжении процесса-отправителя имеется только вызов типа sendMessage - посылки сообщения в очередь. Если при попытке процесса послать сообщение обнаруживается, что очередь заполнена, процесс-отправитель блокируется. Это, впрочем, довольно редкий случай, так как системные ограничения на размер очередей никогда не бывают слишком жесткими. Процесс-получатель блокируется при попытке читать сообщение, когда очередь пуста.
Существенным вопросом при конструировании механизма очередей является вопрос о включении или невключении в ОС системной буферизации сообщений.
При включении такого средства (рис.9.2) тело посылаемого сообщения копируется в системную область памяти, а при чтении - копируется из нее в адресное пространство процесса-получателя. При отсутствии системной буферизации тела сообщений хранятся в общей для отправителя и получателя памяти, а передается только указатель на тело сообщения (рис.9.3). В первом случае выполняются дополнительные пересылки, затрачивается дополнительная память и вводятся более жесткие ограничения на объем сообщений, но достигается надежность передачи и значительно более простой интерфейс процессов. Во втором случае значительно экономится память, но сами процессы должны заботиться об управлении совместно используемой памятью и о сохранности сообщений в ней. При отсутствии системной буферизации сообщений применяются обычно два метода передачи тела сообщения: либо процесс-отправитель помещает тело сообщения в отдельный разделяемый сегмент, получает у ОС манипулятор этого сегмента для процесса-получателя и передает этот манипулятор в составе сообщения; либо для всех сообщений выделяется одна общая область памяти с общим манипулятором, и для размещения сообщения в нем используются системные вызовы выделения памяти в куче.
Рис.9.2. Размещение сообщений в адресном пространстве ядра |
Рис.9.3. Размещение сообщений в адресном пространстве процесса-отправителя |