Процесс может получить данные из потока с помощью системных вызовов M_DATA
и M_PROTO
, при этом сохраняются границы сообщений. Например, если полученное сообщение состоит из блока M_PROTO
и нескольких блоков M_DATA
, вызов
Вызов
#include
int getmsg(int fildes, struct strbuf *ctlptr,
struct strbuf *dataptr, int *flagsp);
С помощью вызова ctlptr
и dataptr
соответственно. Так же как и в случае strbuf
, которая отличается только тем, что поле maxlen
определяет максимальный размер буфера, a len
устанавливается равным фактическому числу полученных байтов. По умолчанию RS_HIPRI
, установленного в переменной, адресуемой аргументом flagsp
, процесс может потребовать получение только экстренных сообщений.
В обоих случаях, если данные находятся в головном модуле, ядро извлекает их из сообщения, копирует в адресное пространство процесса и возвращает управление последнему. Если же в головном модуле отсутствуют сообщения, ожидающие получения, выполнение процесса блокируется, и он переходит в состояние сна до прихода сообщения.
Когда головной модуль получает сообщение, ядро проверяет, ожидает ли его какой-либо процесс. Если такой процесс имеется, ядро пробуждает процесс, копирует данные в пространство задачи и производит возврат из системного вызова. Если ни один из процессов не ожидает получения сообщения, оно буферизуется в очереди чтения головного модуля.
Как и для обычных драйверов устройств, рассмотренных ранее, прежде чем процесс сможет получить доступ к драйверу STREAMS, необходимо встроить драйвер в ядро системы и создать специальный файл устройства — файловый интерфейс доступа. Независимо от того, как именно осуществляется встраивание (статически с перекомпиляцией ядра, или динамически), для этого используются три структуры данных, определенных для любого драйвера или модуля STREAMS: module_info
, qinit
и streamtab
. Связь между ними представлена на рис. 5.21.
Рис. 5.21. Конфигурационные данные драйвера (модуля) STREAMS
Структура streamtab
используется ядром для доступа к точкам входа драйвера или модуля — к процедурам его очередей
,
,
и
. Для этого streamtab
содержит два указателя на структуры qinit
, соответственно, для обработки сообщений очереди чтения и записи. Два других указателя, также на структуры qinit
, используются только для мультиплексоров для обработки команды I_LINK
, используемой при конфигурации мультиплексированного потока. Каждая структура qinit
определяет процедуры, необходимые для обработки сообщений вверх и вниз по потоку (очередей чтения и записи). Функции
и
являются общими для всего модуля и определены только для очереди чтения. Все очереди модуля имеют ассоциированную с ними процедуру
, в то время как процедура
определяется только для очередей, реализующих управление передачей. Каждая структура qinit
также имеет указатель на структуру module_info
, которая обычно определяется для всего модуля и хранит базовые значения таких параметров, как максимальный и минимальный размеры передаваемых пакетов данных (mi_maxpsz
, mi_minpsz
), значения ватерлиний (mi_hiwat
, mi_lowait
), а также идентификатор и имя драйвера (модуля) (mi_idnum
, mi_idname
).
Доступ к драйверам STREAMS осуществляется с помощью коммутатора символьных устройств — таблицы cdevsw[]
. Каждая запись этой таблицы имеет поле d_str
, которое равно NULL
для обычных символьных устройств. Для драйверов STREAMS это поле хранит указатель на структуру streamtab
драйвера. Таким образом, через коммутатор устройств ядро имеет доступ к структуре streamtab
драйвера, а значит и к его точкам входа. Для обеспечения доступа к драйверу из прикладного процесса необходимо создать файловый интерфейс — т.е. специальный файл символьного устройства, старший номер которого был бы равен номеру элемента cdevsw[]
, адресующего точки входа драйвера.
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии