Операционная система UNIX - Робачевский Андрей Михайлович
Шрифт:
Интервал:
Закладка:
Помимо указанных полей, структура queue содержит параметры для обеспечения управления потоком данных — верхнюю и нижнюю ватерлинии очереди.
Передача данных вверх или вниз по потоку осуществляется с помощью функций модуля, указатели на которые хранятся в структуре qinit. Модуль должен определить четыре процедуры для обработки каждой из очередей: <i>xx</i>put(), <i>xx</i>service(), <i>xx</i>open() и <i>xx</i>close(), где xx, как и прежде, обозначает уникальный префикс драйвера. Эти функции адресуются указателями (*qi_putp)(), (*qi_srvp)(), (*qi_qopen)(), (*qi_close)(). Этих четырех функций достаточно для взаимодействия с соседними модулями, обработки и передачи данных. Функция <i>xx</i>open() вызывается каждый раз, когда процесс открывает поток или при встраивании модуля. Соответственно функция <i>xx</i>close() вызывается при закрытии потока или извлечении модуля. Функция <i>xx</i>put() осуществляет обработку сообщений, проходящих через модуль. Если <i>xx</i>put() не может передать сообщение следующему модулю (например, в случае, если очередь следующего модуля переполнена), она помещает сообщение в собственную очередь. Периодически ядро вызывает процедуру <i>xx</i>service() каждого модуля для передачи отложенных сообщений.
Модуль должен иметь функцию <i>xx</i>put() для каждой очереди. Функция <i>xx</i>service() может не существовать, в этом случае <i>xx</i>put() не имеет возможности отложить передачу сообщения и должна передать его немедленно, даже если очередь следующего модуля переполнена. Таким образом модули, не имеющие процедур <i>xx</i>service(), не обладают возможностью управления потоком данных. Эти аспекты мы подробнее рассмотрим в следующих разделах.
Оставшиеся поля структуры qinit:
module_info В этой структуре хранятся базовые значения таких параметров, как ватерлинии, размер сообщений и т.д. Некоторые из этих параметров также находятся в структуре queue. Это дает возможность динамически изменять их, сохраняя при этом базовые значения. module_stat Эта структура непосредственно не используется подсистемой STREAMS. Однако модуль имеет возможность осуществлять сбор разнообразной статистики своего участка потока с помощью полей этой структуры.Сообщения
В подсистеме STREAMS все данные передаются в виде сообщений. С помощью сообщений передаются данные от приложений к драйверу и обратно. Сообщения используются для взаимодействия модулей между собой. Модули могут также генерировать сообщения для уведомления прикладного процесса или друг друга о возникновении ошибок или непредвиденных ситуаций. Таким образом, сообщения являются единственным способом передачи информации между различными компонентами потока и потому занимают ключевое место в подсистеме STREAMS.
Сообщение описывается двумя структурами данных: заголовком сообщения msgb (message block) и заголовком блока данных datab (data block). Обе эти структуры адресуют буфер данных, где находятся фактические данные сообщения.
Заголовок сообщения msgb имеет следующие поля:
b_next, b_prev Используются для формирования связанного списка сообщений и соответственно адресуют следующее и предыдущее сообщение очереди b_cont Указывает на продолжение сообщения и используется для связывания различных частей одного сообщения b_datap Указатель на заголовок блока данных b_rptr, b_wptr Указатели, определяющие расположение (начало и конец) данных в буфере данных b_cont Содержит ссылку на следующую структуру msgbЗаголовок блока данных datab используется для описания буфера и имеет следующие поля:
db_base Адрес начала буфера db_lim Адрес ячейки памяти, следующей непосредственно за буфером. Таким образом, размер буфера равен db_lim - db_base db_type Тип сообщения db_ref Число заголовков сообщения, адресующих этот блокИспользование этих структур данных для формирования очереди сообщений и сообщений, состоящих из нескольких частей, показано на рис. 5.17.
Рис. 5.17. Сообщения STREAMS
Поле b_cont заголовка сообщения позволяет объединять несколько блоков данных в одно сообщение. Эта возможность особенно полезна при использовании подсистемы STREAMS для реализации сетевых протоколов. Сетевые протоколы имеют уровневую организацию. По мере передачи данных вниз по потоку, каждый последующий модуль (реализующий протокол определенного уровня) добавляет собственную управляющую информацию. Поскольку протоколы верхнего уровня не имеют представления об архитектуре нижних, невозможно заранее зарезервировать необходимую память под сообщение. Вместо того чтобы изменять размер буфера данных сообщения, модуль может добавлять управляющую информацию в виде отдельных частей, связывая их с помощью указателя b_cont. Этот процесс, получивший название инкапсуляции данных, графически представлен на рис. 5.18.
Рис. 5.18. Инкапсуляция данных с использованием составных сообщений
Поле db_ref заголовка блока данных позволяет нескольким заголовкам сообщения совместно использовать один и тот же буфер. При этом происходит виртуальное копирование сообщения, каждая копия которого может обрабатываться отдельно. Как правило, такой буфер используется совместно только для чтения, хотя сама подсистема STREAMS не накладывает никаких ограничений, возлагая всю ответственность за обработку данных на модули потока.