UNIX: разработка сетевых приложений
Шрифт:
31.2. Обзор
Потоки обеспечивают двустороннее соединение между процессом и драйвером, как показано на рис. 31.1. Хотя нижний блок на этом рисунке мы и называем драйвером, его не следует ассоциировать с каким-либо аппаратным устройством, поскольку это может быть и драйвер псевдоустройства (например, программный драйвер).
Рис. 31.1. Поток между процессом и драйвером
Головной модуль потока( stream head) состоит из программ ядра, которые запускаются при обращении приложения к дескриптору потока (например, при вызове функций
Процесс может динамически добавлять и удалять промежуточные модули обработки( processing modules) между головным модулем и драйвером. Такой модуль осуществляет некий тип фильтрации сообщений, проходящих в одну или другую сторону по потоку. Этот процесс показан на рис. 31.2.
Рис. 31.2. Поток с модулем обработки
В поток может быть помещено любое количество модулей. Под словом «поместить» (push) в данном случае понимается, что каждый новый модуль вставляется сразу после (на рисунке — ниже) головного модуля.
Определенный тип псевдодрайвера называется мультиплексором( multiplexor). Он принимает данные из различных источников. Основанная на потоках реализация набора протоколов TCP/IP, используемая, например, в SVR4, может иметь вид, показанный на рис. 31.3.
Рис. 31.3. Упрощенный вид реализации набора протоколов TCP/IP, основанной на потоках
При создании сокета библиотекой сокетов в поток помещается модуль
При создании точки доступа XTI библиотекой XTI в поток помещается модуль
Это одно из немногих мест, где мы говорим об XTI. Предыдущее издание этой книги описывало интерфейс XTI очень подробно, но он уже вышел из широкого употребления, и даже спецификация POSIX больше не включает его, поэтому мы решили исключить ставшие ненужными главы из книги. На рис. 31.3 показано, каким образом обычно реализуется интерфейс XTI. В этой главе мы кратко расскажем о нем, но не будем вдаваться в подробности, потому что причин для использования XTI в настоящее время практически нет.
Для использования функций
Формат сетевых сообщений, передаваемых по потокам вверх и вниз, определяют интерфейсы различных сервисов. Мы описываем три наиболее широко распространенных. TPI( Transport Provider Interface — интерфейс поставщика транспортных служб) [126] определяет интерфейс, предоставляемый поставщиком услуг транспортного уровня (например, TCP или UDP). NPI( Network Provider Interface — интерфейс поставщика сетевого уровня) [125] определяет интерфейс, предоставляемый поставщиком услуг сетевого уровня (например, IP). DLPI( Data Link Provider Interface) — это интерфейс поставщика канального уровня[124]. Еще один источник информации по TPI и DLPI, в котором имеются также исходные коды на языке С, — это [98].
Каждый компонент потока — головной модуль, все модули обработки и драйвер — содержат по меньшей мере одну пару очередей: очередь на запись и очередь на чтение. Это показано на рис. 31.4.
Рис. 31.4. Каждый компонент потока содержит по меньшей мере одну пару очередей
Типы сообщений
Потоковые сообщения могут быть классифицированы как имеющие высокий приоритет( high priority), входящие в полосу приоритета( priority band) и обычные ( normal). Существует 256 полос приоритета со значениями между 0 и 255, причем обычные сообщения соответствуют полосе 0. Приоритет потокового сообщения используется как при постановке сообщения в очередь, так и для управления потоком (flow control). По соглашению, на сообщения с высоким приоритетом управление потоком не влияет.
На рис. 31.5 показан порядок следования сообщений в одной конкретной очереди.
Рис. 31.5. Порядок следования потоковых сообщений в очереди в зависимости от их приоритета
Хотя потоковые системы поддерживают 256 различных полос приоритета, в сетевых протоколах обычно используется полоса 1 для срочных (внеполосных) данных и полоса 0 для обычных данных.
Внеполосные данные TCP в TPI не рассматриваются как истинные срочные данные. В самом деле, в TCP полоса 0 используется как для обычных, так и для внеполосных данных. Полоса 1 используется для отправки срочных данных в тех протоколах, в которых срочные данные (а не просто срочный указатель, как в TCP) отправляются перед обычными данными. В данном контексте следует внимательно отнестись к термину «обычный» (normal). В системах SVR, предшествующих SVR4, не было полос приоритета, а сообщения делились на обычные и приоритетные (priority messages). В SVR4 были введены полосы приоритета, что потребовало также введения функций getpmsg и putpmsg, которые мы вскоре опишем. Приоритетные сообщения были переименованы в сообщения с высоким приоритетом, и встал вопрос, как называть сообщения, относящиеся к полосам приоритета от 1 до 255. Наиболее распространенной является терминология [98], согласно которой все сообщения, которые не являются сообщениями с высоким приоритетом, называются обычными сообщениями и разделяются на подкатегории согласно своим полосам приоритета. Термин «обычное сообщение» в любом случае должен соответствовать сообщению из полосы приоритета 0.
Хотя пока мы говорили только о сообщениях с высоким приоритетом и об обычных сообщениях, существует около 12 типов обычных сообщений и около 18 типов сообщений с высоким приоритетом. С точки зрения приложений и функций
Таблица 31.1. Типы потоковых сообщений, генерируемые функциями write и putmsg
Функция | Управляющая информация? | Данные? | Флаги | Генерируемый тип сообщения |
---|---|---|---|---|
write | Да | M_DATA | ||
putmsg | Нет | Да | 0 | M_DATA |
putmsg | Да | Все равно | 0 | M_PROTO |
putmsg | Да | Все равно | MSG_HIPRI | M_PCPROTO |
31.3. Функции getmsg и putmsg
Данные, передаваемые в обоих направлениях по потоку, состоят из сообщений, а каждое сообщение содержит данные, управляющую информациюили и то и другое. Если мы используем функции