Следующая структура данных, которую мы рассмотрим, относится к коммуникационным протоколам. Каждый модуль протокола представляет собой набор функций обработки и структур данных и описывается структурой данных, называемой коммутатором протокола . Коммутатор протокола хранит адреса стандартных функций протокола, например, функций ввода ( 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 представляет собой псевдоустройство, используемое для унифицированного взаимодействия сетевых процессов в рамках одного хоста, отладки и т.п.
Читать дальше