Читаем Операционная система UNIX полностью

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

С помощью мультиплексирующих драйверов потоки, представленные на рис. 5.14, могут быть объединены в единый драйвер протоколов, поддерживающий несколько каналов передачи данных. Именно таким образом реализована поддержка сети во многих версиях операционной системы UNIX. Возможная организация компонентов STREAMS приведена на рис. 5.15.

Рис. 5.15. Конфигурация сетевого доступа с использованием подсистемы STREAMS

В этом случае модули TCP и UDP являются верхними мультиплексорами, а модуль IP реализован в виде гибридного мультиплексора[58]. Такая организация позволяет приложениям создавать потоки, используя различные комбинации сетевых протоколов и драйверов сетевых устройств. Задача мультиплексирующего драйвера помимо обработки данных заключается в хранении состояния всех потоков и правильной маршрутизации данных между ними, т. е. передаче данных в очередь требуемого модуля.

<p>Модули</p>

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

Рис. 5.16. Модуль STREAMS

Каждая очередь представлена структурой данных queue. Наиболее важными полями queue являются:

q_qinfoУказатель на структуру qinit, описывающую функции обработки сообщений данной очереди.
q_first, q_lastУказатели на связанный список сообщений, ожидающих передачи вверх или вниз по потоку.
q_nextУказатель на очередь следующего модуля вверх или вниз по потоку.
q_ptrУказатель на внутренние данные модуля (очереди).

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

Передача данных вверх или вниз по потоку осуществляется с помощью функций модуля, указатели на которые хранятся в структуре qinit. Модуль должен определить четыре процедуры для обработки каждой из очередей: xxput(), xxservice(), xxopen() и xxclose(), где xx, как и прежде, обозначает уникальный префикс драйвера. Эти функции адресуются указателями (*qi_putp)(), (*qi_srvp)(), (*qi_qopen)(), (*qi_close)(). Этих четырех функций достаточно для взаимодействия с соседними модулями, обработки и передачи данных. Функция xxopen() вызывается каждый раз, когда процесс открывает поток или при встраивании модуля. Соответственно функция xxclose() вызывается при закрытии потока или извлечении модуля. Функция xxput() осуществляет обработку сообщений, проходящих через модуль. Если xxput() не может передать сообщение следующему модулю (например, в случае, если очередь следующего модуля переполнена), она помещает сообщение в собственную очередь. Периодически ядро вызывает процедуру xxservice() каждого модуля для передачи отложенных сообщений.

Модуль должен иметь функцию xxput() для каждой очереди. Функция xxservice() может не существовать, в этом случае xxput() не имеет возможности отложить передачу сообщения и должна передать его немедленно, даже если очередь следующего модуля переполнена. Таким образом модули, не имеющие процедур xxservice(), не обладают возможностью управления потоком данных. Эти аспекты мы подробнее рассмотрим в следующих разделах.

Оставшиеся поля структуры qinit:

Перейти на страницу:

Похожие книги