Операционная система UNIX
Шрифт:
В качестве примера виртуального копирования можно привести реализацию протокола TCP. Протокол TCP является надежным, т.е. данные считаются доставленными только после того, как от получателя поступит подтверждение. Это означает, что протокол должен хранить копии всех отправленных, но не подтвержденных сообщений. Вместо неэффективного физического копирования, производится виртуальное дублирование сообщения, одна копия которого затем передается вниз по потоку (модулю IP), а вторая сохраняется до получения подтверждения. После отправления сообщения драйвером сетевого адаптера, одна из копий будет уничтожена, что выразится в уменьшении поля
Типы сообщений
Каждое сообщение принадлежит определенному типу, определяющему назначение сообщения и его приоритет. В зависимости от типа сообщения попадают в одну из двух категорий: обычные сообщения и приоритетные сообщения. Категория определяет
В подсистеме STREAMS определены следующие типы обычных сообщений:
M_DATA | Содержит обычные данные. Например, системные вызовы read(2) и write(2) осуществляют передачу данных в виде сообщений этого типа. |
M_PROTO | Содержит управляющую информацию. Обычно сообщение этого типа содержит также несколько блоков типа M_DATA . С помощью системных вызовов putmsg(2) и getmsg(2) процесс имеет возможность отправлять и получать как управляющую часть сообщения (блок M_PROTO ), так и данные (блоки M_DATA ). |
M_BREAK | Посылается драйверу устройства для генерации команды break. |
M_PASSFP | Используется в каналах STREAMS (STREAMS pipe) для передачи файлового указателя от одного конца канала к другому. |
M_SIG | Генерируется модулями или драйверами и передается вверх по потоку головному модулю для отправления процессу сигнала. |
M_DELAY | Передается драйверу устройства и указывает задержку между последовательно передаваемыми символами. Как правило, используется при работе с медленными устройствами во избежание переполнения их буферов. |
M_CTL | Используется для взаимодействия модулей потока друг с другом. Все сообщения этого типа уничтожаются головным модулем и, таким образом, не могут распространяться за пределы потока. |
M IOCTL | Формируется головным модулем в ответ на управляющие команды, переданные процессом с помощью системного вызова ioctl(2): I_LINK , I_UNLINK , I_PLINK , I_PUNLINK и I_STR . Эти команды используются для создания мультиплексированных потоков. Последняя команда используется для управления модулями потока. |
M_SETOPTS | Используется для задания различных характеристик головного модуля. |
M_RSE | Зарезервировано для внутреннего использования. Модули и драйверы должны передавать его без изменений. |
Как мы увидим далее, на передачу обычных сообщений влияет механизм управления потоком данных, который может быть реализован модулями потока. Этот механизм не оказывает влияния на передачу приоритетных сообщений. Сообщения этой категории будут переданы следующему модулю, независимо от того, насколько заполнена его очередь. Эти сообщения обеспечивают основное взаимодействие между компонентами потока. Перечисленные ниже сообщения являются высокоприоритетными:
M_COPYIN | Передается вверх по потоку головному модулю и указывает ему скопировать данные от процесса для команды ioctl(2). Сообщение допустимо в интервале между получением сообщения M_IOCTL и сообщения M_IOCACK или M_IOCNAK . |
M_COPYOUT | Передается вверх по потоку головному модулю и указывает ему передать данные, связанные с вызовом ioctl(2), процессу. Сообщение допустимо в интервале между получением сообщения M_IOCTL и сообщений M_IOCACK или M_IOCNAK . |
M_ERROR | Передается вверх по потоку головному модулю и указывает на возникновение ошибки вниз по потоку. Последующие операции с потоком будут заканчиваться ошибкой, за исключением системных вызовов close(2) и poll(2). |
M_FLUSH | При получении этого сообщения модуль должен очистить очередь (чтения, записи или обе) от сообщений. |
M_HANGUP | Передается вверх по потоку головному модулю и указывает, что драйвер не может передавать данные, обычно из-за обрыва линии (связи с удаленным объектом). |
M_IOCACK | Подтверждение предыдущего сообщения M_IOCTL . В ответ головной модуль возвратит необходимые данные процессу, сделавшему системный вызов ioctl(2). |
M_IOCNAK | Если
|
M_PCPROTO | Высокоприоритетная версия сообщения M_PROTO . |
M_PCSIG | Высокоприоритетная версия сообщения M_SIG . |
M_PCRSE | Зарезервировано для внутреннего использования в подсистеме. |
M_READ | Сообщение передается вниз по потоку, когда от процесса поступает запрос на чтение, но в головном модуле отсутствуют данные. |
M_STOP | Предписывает немедленно прекратить передачу. |
M_START | Предписывает продолжить передачу после останова, вызванного сообщением M_STOP . |
Передача данных
Как уже обсуждалось, передача данных в потоке происходит в виде сообщений. Процесс инициирует передачу данных с помощью системных вызовов write(2) и putmsg(2), которые непосредственно взаимодействуют с головным модулем. Головной модуль формирует сообщение, копируя в него прикладные данные, и передает его следующему модулю вниз по потоку. В конечном итоге сообщение принимается драйвером, который выполняет необходимые операции с конкретным устройством. В случае, когда драйвер получает данные от устройства, он также передает их в виде сообщений вверх по потоку. Процесс имеет возможность получить данные с помощью системных вызовов read(2) или getmsg(2). Если в головном модуле данные отсутствуют, процесс блокируется и переходит в состояние сна.
Сообщения передаются модулями с помощью системной функции putnext(9F):
Эта функция адресует очередь следующего модуля параметром
Передача данных внутри потока осуществляется асинхронно и не может блокировать процесс. Блокирование процесса возможно только при передаче данных между процессом и головным модулем. Таким образом, функции обработки данных потока —
Процедура
Блокирование недопустимо и для драйвера. Обычно прием данных драйвером осуществляется с использованием прерываний. Таким образом процедура
Когда процедура
Функция putq(9F) помещает сообщение mp в очередь q, где сообщение ожидает последующей передачи, и заносит очередь в список очередей, нуждающихся в обработке. Для таких очередей ядро автоматически вызывает процедуру
59
Система планирования STREAMS использует собственные функции и не имеет отношения к планированию процессов в UNIX.