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

ЖАНРЫ

Шрифт:

memcpy(opt.buf, conncon+conncon->OPT_offset, opt.len);

free(confirm.buf);

/* Все закончилось удачно — возвращаем 0 */

return 0;

}

} else {

/* В случае отказа мы готовы обработать примитив

T_DISCON_IND */

...

return -1;

}

 } else {

/* Если получен примитив T_ERROR_ACK — обработаем его */

errack = (struct T_error_ack*)ack.buf;

...

return -1;

 }

}

Подобным

образом реализовано большинство функций TLI. Заметим, что в конкретном случае использования транспортного протокола TCP прием и передача данных осуществляются в виде потока, не содержащего каких-либо логических записей. В этом случае не требуется формирование примитивов типа
T_DATA_REQ
и
T_DATA_IND
. В то же время, для передачи и получения экстренных данных будут использованы примитивы
T_EXDATA_REQ
и
T_EXDATA_IND
. При использовании протокола UDP все данные будут передаваться с помощью примитивов
T_UNITDATA_REQ
и
T_UNITDATA_IND
.

Описанная реализация программного интерфейса TLI имеет один существенный недостаток — операции функций не являются атомарными. Другими словами, выполнение функции t_connect(3N) может быть прервано другими процессами, которые могут также связываться с удаленным узлом. Это возможно, поскольку выполнение значительной части операций происходит в режиме задачи. Если для функции t_connect(3N) нарушение атомарности допустимо, то ряд функций, таких, например, как связывание (t_bind(3N)), получение информации (t_open(3N), t_getinfo(3N)) и установка или получение опций протокола (t_optmgmt(3N)) должны быть защищены от возможного нарушения целостности данных по причине прерывания операции. Единственным способом гарантировать атомарность является перевод выполнения критических участков (например, между отправлением примитива и получением подтверждения от поставщика транспортных услуг) в режим ядра. Для этого подсистема STREAMS предлагает механизм обмена управляющими командами с помощью вызова ioctl(2).

Однако с помощью ioctl(2), как было показано в разделе "Подсистема STREAMS" главы 5, можно формировать лишь сообщения типа

M_IOCTL
. Для преобразования этих сообщений в примитивы TPI служит дополнительный модуль timod(7M), встраиваемый в поток между головным и транспортным модулями. На рис. 6.33 показано местоположение модуля timod(7M) и схематически отображены его функции.

Рис. 6.33. Архитектура доступа к транспортным услугам

Для всех сообщений STREAMS, за исключением сообщений

M_IOCTL
, которые генерируются головным модулем в ответ на системный вызов
ioctl(fd, I_STR, ...)
, модуль timod(7M) является прозрачным, т.е. он просто передает эти сообщения следующему модулю вниз по потоку без какой-либо обработки. Несколько сообщений
M_IOCTL
обрабатываются модулем и преобразуются в соответствующие примитивы TPI.

При этом вызов ioctl(2) имеет следующий формат:

#include <sys/stropts.h>

struct strioctl my_strioctl

...

strioctl.ic_cmd = cmd;

strioctl.ic_timeout = INFTIM;

strioctl.ic_len = size;

strioctl.ic_dp = (char*)buf;

ioctl(fd, I_STR, &my_strioctl);

При вызове ioctl(2) поле

size
устанавливается равным размеру соответствующего примитива TPI, определенного полем
cmd
и расположенного в буфере
buf
.
При возврате из функции поле
size
содержит размер примитива, возвращенного поставщиком транспортных услуг и расположенного в буфере buf.

Модуль timod(7M) служит для обработки следующих команд cmd:

Значение cmd Обработка модулем timod(7M)
TI_BIND
Команда преобразуется в примитив
T_BIND_REQ
. При успешном завершении функции ioctl(2) в буфере
buf
находится примитив
T_BIND_ACK
.
TI_UNBIND
Команда преобразуется в примитив
T_UNBIND_REQ
. При успешном завершении функции ioctl(2) в буфере
buf
находится примитив
T_OK_ACK
.
TI_GETINFO
Команда преобразуется в примитив
T_INFO_REQ
. При успешном завершении функции ioctl(2) в буфере
buf
находится примитив
T_INFO_ACK
.
TI_OPTMGMT
Команда преобразуется в примитив
T_OPTMT_REQ
. При успешном завершении функции ioctl(2) в буфере
buf
находится примитив
T_OPTMGMT_ACK
.

Интерфейс DLPI

DLPI определяет интерфейс между протоколами уровня канала данных (data link layer) модели OSI, называемыми поставщиками услуг уровня канала данных и протоколами сетевого уровня, называемыми пользователями услуг уровня канала данных. В качестве примера пользователей услуг уровня канала данных можно привести такие протоколы, как IP, IPX или CLNS. С другой стороны, поставщик услуг уровня канала данных непосредственно взаимодействует с различными сетевыми устройствами, обеспечивающими передачу данных по сетям различной архитектуры (например, Ethernet, FDDI или ATM) и использующими различные физические среды передачи.

Для обеспечения независимости DLPI от конкретной физической сети передачи драйвер уровня канала данных состоит из двух частей: верхней аппаратно-независимой и нижней аппаратно-зависимой. Аппаратно-независимая часть драйвера обеспечивает предоставление общих услуг, определенных интерфейсом DLPI, а также поддержку ряда потенциальных пользователей, представляющих семейства протоколов TCP/IP, NetWare и OSI. Аппаратно-зависимая часть непосредственно взаимодействует с сетевым адаптером.

На рис. 6.34 приведена структура драйвера поставщика услуг уровня канала данных. Обмен данными между аппаратно-независимой частью драйвера и пользователем услуг осуществляется в виде сообщений STREAMS, формат и назначение которых и определяется спецификацией DLPI (т.н. примитивы DLPI).

Рис. 6.34. Структура драйвера уровня канала данных

Во время инициализации и последующей передачи данных аппаратно-независимая часть драйвера вызывает необходимые функции аппаратно-зависимой части. Напротив, при поступлении данных из сети, аппаратно-зависимая часть помещает пакеты данных, или кадры, непосредственно в очередь чтения аппаратно-независимой части. Обе части совместно используют набор переменных и флагов для взаимной синхронизации и контроля передачи.

Пользователь получает доступ к услугам поставщика услуг уровня канала данных через точку доступа к услугам (Service Access Point, SAP), используя сообщения STREAMS для обмена данными. Поскольку один поставщик может иметь несколько пользователей, например IP и IPX, в его задачу входит маршрутизация данных, полученных от физической сети, к нескольким точкам доступа. Для этого каждый пользователь идентифицирует себя с помощью адреса SAP, который сообщает поставщику, используя примитив связывания (

DL_BIND_REQ
) потока с точкой доступа к услугам уровня канала данных.

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