Операционная система UNIX
Шрифт:
Рис. 5.13. Базовая архитектура потока
Процесс взаимодействует с потоком, используя стандартные системные вызовы open(2), close(2), read(2), write(2) и ioctl(2). Дополнительные функции работы с потоками включают poll(2), putmsg(2) и getmsg(2). Передача данных по потоку осуществляется в виде сообщений, содержащих данные, тип сообщения и управляющую информацию. Для передачи данных каждый модуль, включая головной модуль и сам драйвер, имеет две очереди — очередь чтения (read queue) и очередь записи (write queue).
Сообщения также могут передаваться в парную очередь. Другими словами, из очереди записи модуля 1 сообщение может быть направлено в очередь чтения того же модуля, а затем, при необходимости, передано вверх по потоку. При этом модулю нет необходимости знать, какой части потока принадлежит следующая очередь — головному или промежуточному модулю, или драйверу. Такой подход позволяет производить разработку модулей независимо друг от друга и использовать их затем в различных комбинациях и в различных потоках.
Подсистема STREAMS обеспечивает возможность такой комбинации благодаря механизму динамического встраивания (push) модуля в поток. Встраивание модуля возможно непосредственно после головного модуля. При этом будут установлены связи между соответствующими очередями встраиваемого модуля, головного модуля и модулей вниз по потоку. После этого встроенный модуль будет производить определенную обработку проходящих данных, тем самым изменяя изначальную функциональность потока. При необходимости модуль может быть извлечен (pop) из потока.
На рис. 5.14 показаны различные потоки, созданные из нескольких стандартных компонентов, для поддержки сетевых протоколов семейства TCP/IP. Причем модули IP, TCP и UDP могут поставляться одним производителем, а драйверы Ethernet или Token Ring соответствующими производителями сетевых адаптеров. В результате встраивания необходимых модулей первый поток будет обеспечивать передачу трафика TCP через адаптер Ethernet, в то время как второй — передачу трафика UDP через адаптер Token Ring.
Рис. 5.14. Использование одних и тех же модулей для создания различных потоков
Подсистема STREAMS также обеспечивает возможность мультиплексирования потоков. Мультиплексирующий драйвер может быть подключен к нескольким модулям как вверх, так и вниз по потоку. Различают три типа мультиплексоров — верхний, обеспечивающий мультиплексирование вверх по потоку, нижний, обеспечивающий мультиплексирование вниз по потоку, и гибридный, поддерживающий несколько потоков выше и ниже мультиплексора.
С помощью мультиплексирующих драйверов потоки, представленные на рис. 5.14, могут быть объединены в единый драйвер протоколов, поддерживающий несколько каналов передачи данных. Именно таким образом реализована поддержка сети во многих версиях операционной системы UNIX. Возможная организация компонентов STREAMS приведена на рис. 5.15.
Рис. 5.15. Конфигурация сетевого доступа с использованием подсистемы STREAMS
В этом случае модули TCP и UDP являются верхними мультиплексорами, а модуль IP реализован в виде гибридного мультиплексора [58] . Такая организация позволяет приложениям создавать потоки, используя различные комбинации сетевых протоколов и драйверов сетевых устройств. Задача мультиплексирующего драйвера помимо обработки данных заключается в хранении состояния всех потоков и правильной маршрутизации данных между ними, т. е. передаче данных в очередь требуемого модуля.
58
На самом деле мультиплексором может являться только драйвер STREAMS. Объединение драйверов в единый объект отлично от встраивания модулей и носит название связывания. Более подробно связывание
и различия между модулями и драйверами STREAMS мы рассмотрим несколько позже в этой главе.Модули
Модули являются основными компонентами потока. Каждый модуль состоит из пары очередей — очереди чтения и записи, а также набора функций, осуществляющих обработку данных и их передачу вверх или вниз по потоку. Архитектура модуля представлена на рис. 5.16.
Рис. 5.16. Модуль STREAMS
Каждая очередь представлена структурой данных
q_qinfo | Указатель на структуру qinit , описывающую функции обработки сообщений данной очереди. |
q_first , q_last | Указатели на связанный список сообщений, ожидающих передачи вверх или вниз по потоку. |
q_next | Указатель на очередь следующего модуля вверх или вниз по потоку. |
q_ptr | Указатель на внутренние данные модуля (очереди). |
Помимо указанных полей, структура
Передача данных вверх или вниз по потоку осуществляется с помощью функций модуля, указатели на которые хранятся в структуре
Модуль должен иметь функцию
Оставшиеся поля структуры
module_info | В этой структуре хранятся базовые значения таких параметров, как ватерлинии, размер сообщений и т.д. Некоторые из этих параметров также находятся в структуре queue. Это дает возможность динамически изменять их, сохраняя при этом базовые значения. |
module_stat | Эта структура непосредственно не используется подсистемой STREAMS. Однако модуль имеет возможность осуществлять сбор разнообразной статистики своего участка потока с помощью полей этой структуры. |