`
Читать книги » Книги » Компьютеры и Интернет » Интернет » Операционная система UNIX - Робачевский Андрей Михайлович

Операционная система UNIX - Робачевский Андрей Михайлович

Перейти на страницу:

□ Трансляцию данных, передаваемых процессом с помощью системных вызовов, в сообщения и передачу их вниз по потоку.

□ Сообщение об ошибках и отправление сигналов процессам, связанным с потоком.

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

Процесс передает данные потоку с помощью системных вызовов write(2) и putmsg(2). Системный вызов write(2), представляющий собой унифицированный интерфейс передачи данных любым устройствам, позволяет производить передачу простых данных в виде потока байтов, не сохраняя границы логических записей. Системный вызов putmsg(2), предназначенный специально для работы с потоками, позволяет процессу за один вызов передать управляющее сообщение и данные. Головной модуль преобразует эту информацию в единое сообщение с сохранением границ записи.

Системный вызов putmsg(2) имеет вид:

#include <stropts.h>

int putmsg(int fildes, const struct strbuf *ctlptr,

 const struct strbuf* dataptr, int flags);

С помощью этого вызова головной модуль формирует сообщение, состоящее из управляющей части M_PROTO и данных, передаваемых в блоках M_DATA. Содержимое сообщения передается с помощью указателей на структуру strbuf — ctlptr для управляющего блока и dataptr для блоков данных.

Структура strbuf имеет следующий формат:

struct strbuf {

 int maxlen;

 int len;

 void *buf;

}

где maxlen не используется, len — размер передаваемых данных, buf — указатель на буфер.

С помощью аргумента flags процесс может передавать экстренные сообщения, установив флаг RS_HIPRI.

В обоих случаях головной модуль формирует сообщение и с помощью функции canput(9F) проверяет, способен ли следующий вниз по потоку модуль, обеспечивающий механизм управления передачей, принять его. Если canput(9F) возвращает истинный ответ, сообщение передается вниз по потоку с помощью функции putnext(9F), а управление возвращается процессу. Если canput(9F) возвращает ложный ответ, выполнение процесса блокируется, и он переходит в состояние сна, пока не рассосется образовавшийся затор. Заметим, что возврат системного вызова еще не гарантирует, что данные получены устройством. Возврат из write(2) или putmsg(2) свидетельствует лишь о том, что данные были успешно скопированы в адресное пространство ядра, и в виде сообщения направлены вниз по потоку.

Процесс может получить данные из потока с помощью системных вызовов read(2) и getmsg(2). Стандартный вызов read(2) позволяет получать только обычные данные без сохранения границ сообщений.[63] В отличие от этого вызова getmsg(2) позволяет получать данные сообщений типов M_DATA и M_PROTO, при этом сохраняются границы сообщений. Например, если полученное сообщение состоит из блока M_PROTO и нескольких блоков M_DATA, вызов getmsg(2) корректно разделит сообщение на две части: управляющую информацию и собственно данные.

Вызов getmsg(2) имеет вид:

#include <stropts.h>

int getmsg(int fildes, struct strbuf *ctlptr,

 struct strbuf *dataptr, int *flagsp);

С помощью вызова getmsg(2) прикладной процесс может получить сообщение, причем его управляющие и прикладные данные будут помещены в буферы, адресуемые ctlptr и dataptr соответственно. Так же как и в случае putmsg(2) эти указатели адресуют структуру strbuf, которая отличается только тем, что поле maxlen определяет максимальный размер буфера, a len устанавливается равным фактическому числу полученных байтов. По умолчанию getmsg(2) получает первое полученное сообщение, однако с помощью флага RS_HIPRI, установленного в переменной, адресуемой аргументом flagsp, процесс может потребовать получение только экстренных сообщений.

В обоих случаях, если данные находятся в головном модуле, ядро извлекает их из сообщения, копирует в адресное пространство процесса и возвращает управление последнему. Если же в головном модуле отсутствуют сообщения, ожидающие получения, выполнение процесса блокируется, и он переходит в состояние сна до прихода сообщения.

Когда головной модуль получает сообщение, ядро проверяет, ожидает ли его какой-либо процесс. Если такой процесс имеется, ядро пробуждает процесс, копирует данные в пространство задачи и производит возврат из системного вызова. Если ни один из процессов не ожидает получения сообщения, оно буферизуется в очереди чтения головного модуля.

Доступ к потоку

Как и для обычных драйверов устройств, рассмотренных ранее, прежде чем процесс сможет получить доступ к драйверу STREAMS, необходимо встроить драйвер в ядро системы и создать специальный файл устройства — файловый интерфейс доступа. Независимо от того, как именно осуществляется встраивание (статически с перекомпиляцией ядра, или динамически), для этого используются три структуры данных, определенных для любого драйвера или модуля STREAMS: module_info, qinit и streamtab. Связь между ними представлена на рис. 5.21.

Рис. 5.21. Конфигурационные данные драйвера (модуля) STREAMS

Структура streamtab используется ядром для доступа к точкам входа драйвера или модуля — к процедурам его очередей <i>xx</i>open(), <i>xx</i>close(), <i>xx</i>put() и <i>xx</i>service(). Для этого streamtab содержит два указателя на структуры qinit, соответственно, для обработки сообщений очереди чтения и записи. Два других указателя, также на структуры qinit, используются только для мультиплексоров для обработки команды I_LINK, используемой при конфигурации мультиплексированного потока. Каждая структура qinit определяет процедуры, необходимые для обработки сообщений вверх и вниз по потоку (очередей чтения и записи). Функции <i>xx</i>open() и <i>xx</i>close() являются общими для всего модуля и определены только для очереди чтения. Все очереди модуля имеют ассоциированную с ними процедуру <i>xx</i>put(), в то время как процедура <i>xx</i>service() определяется только для очередей, реализующих управление передачей. Каждая структура qinit также имеет указатель на структуру module_info, которая обычно определяется для всего модуля и хранит базовые значения таких параметров, как максимальный и минимальный размеры передаваемых пакетов данных (mi_maxpsz, mi_minpsz), значения ватерлиний (mi_hiwat, mi_lowait), а также идентификатор и имя драйвера (модуля) (mi_idnum, mi_idname).

Перейти на страницу:

Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Операционная система UNIX - Робачевский Андрей Михайлович, относящееся к жанру Интернет. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.

Комментарии (0)