Чтение онлайн

ЖАНРЫ

Шрифт:

Прежде чем более подробно ознакомиться со взаимодействием различных модулей сетевой подсистемы BSD UNIX, рассмотрим сначала структуры данных, определяющие сокет, коммуникационный протокол и сетевой интерфейс.

Структуры данных

Структура данных

socket
, описывающая сокет, представлена на рис. 6.21. В этой структуре хранится информация о типе сокета (
so_type
), его текущем состоянии (
so_state
) и используемом протоколе (
so_proto
).

Рис. 6.21. Структуры данных сокета

Сокет является коммуникационным узлом и обеспечивает буферизацию получаемых и отправляемых данных.

Как только данные попадают в распоряжение сокета в результате системного вызова (например, write(2) или send(2)), сокет немедленно передает их модулю протокола для последующего отправления. Данные передаются в виде связанного списка специальных буферов mbuf, структура которых также показана на рис. 6.21. Модуль протокола может ожидать подтверждения получения отправленных данных или отложить их отправку. В обоих случаях сообщения остаются в буфере передачи сокета до момента окончательной отправки или получения подтверждения. Аналогично, данные, полученные из сети, в конечном итоге буферизуются в приемной очереди сокета-адресата, пока не будут извлечены оттуда системным вызовом (например, read(2) или recv(2)).

Для избежания переполнения буфер (структура

sockbuf
) хранит параметр
sb_hiwat
 — значение верхней ватерлинии. Модуль коммуникационного протокола может использовать это значение для управления потоком данных. Например, модуль TCP устанавливает максимальное значение окна приема равным этому параметру.

Сокеты, используемые для приема и обработки запросов на установление связи (зарегистрированные с помощью системного вызова listen(2)), адресуют два связанных списка: список сокетов, связь для которых не полностью установлена, и список сокетов, обеспечивающих доступ к созданным каналам передачи данных.

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

pr_input
) и вывода (
pr_output
), и выполняет ту же роль, что и элемент коммутатора устройств, рассмотренный в главе 5. Поле so_proto сокета содержит адрес этой структуры для соответствующего протокола. Вид коммутатора протокола показан на рис. 6.22.

Рис. 6.22. Коммутатор протокола

Перед первым использованием модуля вызывается функция его инициализации

pr_init
. После этого система будет вызывать функции таймера модуля протокола
pr_fasttimo
каждые 200 миллисекунд и
pr_slowtimo
каждые 500 миллисекунд, если протокол определил эти функции. Например, модуль протокола TCP использует функции таймера для обработки тайм-аутов при установлении связи и повторных передачах. Функция
pr_drain
вызывается системой при недостатке свободной памяти и позволяет модулю уничтожить некритичные сообщения для освобождения места.

С помощью функции

pr_usrreq
модулю протокола передаются сообщения от прикладного процесса. Таким образом, эта функция определяет интерфейс взаимодействия между сокетом и протоколом нижнего уровня. Одним из параметров этой функции является номер запроса, зависящий от произведенного системного вызова. Интерфейс взаимодействия сокета с прикладными процессами является стандартным интерфейсом системных вызовов и преобразует вызовы bind(2), listen(2), send(2), sendto(2) и т.д. в соответствующие запросы функции
pr_usrreq
. Некоторые из них приведены в табл. 6.7.

Таблица 6.7. Запросы функции pr_usrreq

Системный вызов Значение Запрос
close(2) Прекратить обмен данными
PRU_ABORT
accept(2) Обработать
запрос на установление связи
PRU_ACCEPT
bind(2) Связать сокет с адресом
PRU_BIND
connect(2) Установить связь
PRU_CONNECT
listen(2) Разрешить обслуживание запросов
PRU_LISTEN
send(2), sendto(2) Отправить данные
PRU_SEND
fstat(2) Определить состояние сокета
PRU_SENSE
getsockname(2) Получить адрес локального сокета
PRU_SOCKADDR
getpeername(2) Получить адрес удаленного сокета
PRU_PEERADDR
ioctl(2) Передать команду модулю протокола
PRU_CONTROL

Функции

pr_input
и
pr_output
определяют интерфейс взаимодействия протокол-протокол и служат для передачи данных между модулями соседних уровней. Аналогично для обмена управляющими командами между модулями протоколов используются функции
pr_ctlinput
и
pr_ctloutput
. Цепочка взаимодействующих протоколов производит размещение и освобождение памяти при обмене сообщениями, которые передаются посредством рассмотренных структур
mbuf
: при передаче сообщений от сети прикладному процессу за освобождение буферов
mbuf
отвечает модуль верхнего уровня и наоборот, при передаче сообщений в сеть память, занимаемая сообщением, освобождается на самом нижнем уровне.

Поле

pr_flags
определяет некоторые характеристики протокола и режим его функционирования, которые в основном относятся к уровню сокетов. Например, протоколы, предусматривающие предварительное установление связи, указывают это с помощью флага
PR_CONNREQUIRED
, не позволяя тем самым функциям сокета передавать данные модулю до создания виртуального канала. Если установлен флаг
PR_WANTRCVD
, соответствующие функции сокета будут уведомлять модуль протокола, когда прикладной процесс получает данные из буфера приема. Это может служить сигналом протоколу для отправления подтверждения о получении, а также для обновления значения окна в соответствии с освободившимся местом.

Заметим, что каждый модуль протокола имеет собственные очереди сообщений, используемые для приема и передачи данных.

Каждый сетевой интерфейс системы представлен структурой данных, показанной на рис. 6.23. Сетевой интерфейс обычно связан с соответствующим сетевым адаптером, хотя это не является обязательным условием. Например, внутренний сетевой интерфейс loopback представляет собой псевдоустройство, используемое для унифицированного взаимодействия сетевых процессов в рамках одного хоста, отладки и т.п.

Рис. 6.23. Сетевой интерфейс

Решение об использовании того или иного сетевого интерфейса для передачи сообщения базируется на таблице маршрутизации и производится модулем сетевого уровня. Интерфейс может обслуживать протоколы различных коммуникационных доменов. Соответственно, один и тот же интерфейс может иметь несколько адресов, определенных для каждого семейства протоколов. Структуры, определяющие локальный и широковещательный (broadcast) адреса интерфейса, а также сетевую маску, хранятся в виде связанного списка.

Поделиться с друзьями: