А. Робачевский - Операционная система UNIX (1114671), страница 70
Текст из файла (страница 70)
"Уважительной" причиной прекращения обработкиявляется переполнение очереди следующего по потоку модуля. В против!ном случае нарушается механизм управления передачей, и очередь можетнавсегда лишиться обработки.ДрайверДрайверы и модули очень похожи, они используют одинаковые структурыданных (streamtab, qinit,о) и одинаковый интерфейс(ххорепxxput ( ) , xxservice ( ) и xxcloseОднако между драйве!рами и модулями существуют различия.Во!первых, только драйверы могут непосредственно взаимодействовать саппаратурой и отвечать за обработку аппаратных прерываний.
Поэтомудрайвер должен зарегистрировать в ядре соответствующий обработчикпрерываний. Аппаратура обычно генерирует прерывания при полученииданных. В ответ на это драйвер копирует данные от устройства, формируетсообщение и передает его вверх по потоку.Во!вторых, к драйверу может быть подключено несколько потоков. Какуже обсуждалось, на мультиплексировании потоков построены многиеЭто единственнаяв которой возможно блокирование процесса.Более точно — для всех сообщений с данным приоритетом.www.books-shop.comSTREAMS369подсистемы ядра, например, поддержка сетевых протоколов. В качествемультиплексора может выступать только драйвер. Несмотря на то чтодрайвер в этом случае не является оконечным модулем (см., например,рис.
5.15), размещение драйверов существенным образом отличается отвстраивания модулей.Наконец, процесс инициализации драйверов и модулей различен. Функ!ция ххорепдрайвера вызывается при открытии потока, в то время какинициализация модуля происходит при встраивании.Головной модульОбработку системных вызовов процессов осуществляет головной модуль.Головной модуль потока является единственным местом, где возможноблокирование обработки и, соответственно, процесса, в контексте кото!рого осуществляется операция ввода/вывода. Головной модуль являетсявнешним интерфейсом потока, и хотя его структура похожа на структуруобычного модуля, функции обработки здесь обеспечиваются самой под!системой STREAMS.
В отличие от точек входа в модуль или драйвер пото!ка, реализующих специфическую для данного устройства обработку,функции головного модуля выполняют ряд общих для всех потоков задач,включающих:Трансляцию данных, передаваемых процессом с помощью систем!ных вызовов, в сообщения и передачу их вниз по потоку.Сообщение об ошибках и отправление сигналов процессам, связан!ным с потоком.Распаковку сообщений, переданных вверх по потоку, и копированиеданных в пространство ядра или задачи.Процесс передает данные потоку с помощью системных вызововиСистемный вызовпредставляющий собой унифициро!ванный интерфейс передачи данных любым устройствам, позволяет про!изводить передачу простых данных в виде потока байтов, не сохраняя гра!ницы логических записей. Системный вызовпредназначенныйспециально для работы с потоками, позволяет процессу за один вызов пе!редать управляющее сообщение и данные.
Головной модуль преобразуетэту информацию в единое сообщение с сохранением границ записи.Системный вызовимеет вид:<stropts.h>putmsg(int fildes, const structconst struct strbufintС помощью этого вызова головной модуль формирует сообщение, состоя!щее из управляющей части м PROTO и данных, передаваемых в блокахȾɚɧɧɚɹɜɟɪɫɢɹɤɧɢɝɢɜɵɩɭɳɟɧɚɷɥɟɤɬɪɨɧɧɵɦɢɡɞɚɬɟɥɶɫɬɜɨɦ%RRNVVKRSɊɚɫɩɪɨɫɬɪɚɧɟɧɢɟɩɪɨɞɚɠɚɩɟɪɟɡɚɩɢɫɶɞɚɧɧɨɣɤɧɢɝɢɢɥɢɟɟɱɚɫɬɟɣɁȺɉɊȿɓȿɇɕɈɜɫɟɯɧɚɪɭɲɟɧɢɹɯɩɪɨɫɶɛɚɫɨɨɛɳɚɬɶɩɨɚɞɪɟɫɭpiracy@books-shop.comГлава 5.370DATA.
Содержимое сообщения передается с помощью указателей наструктуру strbuf — ctlptr для управляющего блока идля бло!ков данных.Структура strbuf имеет следующий формат:struct strbuf {intint len;void)где m a x l e n не используется, len — размер передаваемых данных, buf —указатель на буфер.С помощью аргументапроцесс может передавать экстренные сооб!щения, установив флаг RS_HIPRI.В обоих случаях головной модуль формирует сообщение и с помощьюфункциипроверяет, способен ли следующий вниз по потоку мо!дуль, обеспечивающий механизм управления передачей, принять его.
Есливозвращает истинный ответ, сообщение передается вниз по пото!ку с помощью функцииа управление возвращается процессу.Есливозвращает ложный ответ, выполнение процесса блокирует!ся, и он переходит в состояние сна, пока не рассосется образовавшийся за!тор. Заметим, что возврат системного вызова еще не гарантирует, что дан!ные получены устройством. Возврат изилисвидетельствуетлишь о том, что данные были успешно скопированы в адресное пространст!во ядра, и в виде сообщения направлены вниз по потоку.Процесс может получить данные из потока с помощью системных вызововиСтандартный вызов read(2) позволяет получать толькообычные данные без сохранения границВ отличие от этоговызовапозволяет получать данные сообщений типовиM_PROTO, при этом сохраняются границы сообщений. Например, если по!лученное сообщение состоит из блока м PROTO и нескольких блоковM_DATA, вызов getmsg(2) корректно разделит сообщение на две части:управляющую информацию и собственно данные.Вызов getmsg(2) имеет вид:ftinclude <stropts.h>intf i l d e s , struct s t r b u fstruct strbuf*ctlptr,intС помощью сообщения м SETOPTS можно дать указания головному модулю обрабатыватьсообщениякак обычные данные.
В этом случае вызовбудет возвращатьсодержимоесообщенийтак иОднако информация осообще!ния (данных) и границы сообщений сохранены не будут.www.books-shop.comSTREAMSС помощью вызоваприкладной процесс может получить сообще!ние, причем его управляющие и прикладные данные будут помещены вбуферы, адресуемыеисоответственно.
Так же как и вслучаеэти указатели адресуют структурукоторая отлича!ется только тем, что полеопределяет максимальный размер буфе!ра, aустанавливается равным фактическому числу полученных байтов.По умолчанию getmsg(2) получает первое полученное сообщение, однако спомощью флага RS_HIPRI, установленного в переменной, адресуемой ар!гументом f l a g s p , процесс может потребовать получение только экстрен!ных сообщений.В обоих случаях, если данные находятся в головном модуле, ядро извлека!ет их из сообщения, копирует в адресное пространство процесса и воз!вращает управление последнему. Если же в головном модуле отсутствуютсообщения, ожидающие получения, выполнение процесса блокируется, ион переходит в состояние сна до прихода сообщения.Когда головной модуль получает сообщение, ядро проверяет, ожидает лиего какой!либо процесс. Если такой процесс имеется, ядро пробуждаетпроцесс, копирует данные в пространство задачи и производит возврат изсистемного вызова.
Если ни один из процессов не ожидает получения со!общения, оно буферизуется в очереди чтения головного модуля.Доступ к потокуКак и для обычных драйверов устройств, рассмотренных ранее, прежде чемпроцесс сможет получить доступ к драйверу STREAMS, необходимо встро!ить драйвер в ядро системы и создать специальный файл устройства — фай!ловый интерфейс доступа. Независимо от того, как именно осуществляетсявстраивание (статически с перекомпиляцией ядра, или динамически), дляэтого используются три структуры данных, определенных для любого драй!вера или модуля STREAMS:qinit и streamtab.
Связь меж!ду ними представлена на рис. 5.21.Структура streamtab используется ядром для доступа к точкам входадрайвера или модуля — к процедурам его очередей ххорепxxclosexxput и xxserviceДля этого s t r e a m t a b содержит два указателя наструктуры qinit, соответственно, для обработки сообщений очереди чте!ния и записи.
Два других указателя, также на структуры q i n i t , использу!ются только для мультиплексоров для обработки команды I_LINK, исполь!зуемой при конфигурации мультиплексированного потока. Каждая струк!тура qinit определяет процедуры, необходимые для обработки сообщенийвверх и вниз по потоку (очередей чтения и записи). Функции ххорепиxxcloseявляются общими для всего модуля и определены только дляочереди чтения. Все очереди модуля имеют ассоциированную с ними про!цедуру xxput ( ) , в то время как процедура() определяетсяwww.books-shop.com5.372только для очередей, реализующих управление передачей. Каждая структу!ра qinit также имеет указатель на структурукоторая обыч!но определяется для всего модуля и хранит базовые значения таких пара!метров, как максимальный и минимальный размеры передаваемых пакетовданныхmi_minpsz), значения ватерлинийа также идентификатор и имя драйвера (модуля) (mi_idnum,mi_idname).Рис.Конфигурационные данные драйвера (модуля) STREAMSДоступ к драйверам STREAMS осуществляется с помощью коммутаторасимвольных устройств — таблицыКаждая запись этой таблицыимеет поле d_str, которое равно NULL для обычных символьных уст!ройств.
Для драйверов STREAMS это поле хранит указатель на структурудрайвера. Таким образом, через коммутатор устройств ядроимеет доступ к структуре streamtab драйвера, а значит и к его точкамвхода. Для обеспечения доступа к драйверу из прикладного процесса необ!ходимо создать файловый интерфейс — т. е. специальный файл символь!ного устройства, старший номер которого был бы равен номеру элементаcdevsw [адресующего точки входа драйвера.Создание потокаПоток создается при первом открытии с помощью системного вызоваспециального файла устройства, ассоциированного с драйвером STREAMS.Как правило, процесс создает поток в два этапа: сначала создается элемен!тарный поток, состоящий из нужного драйвера и головного модуляwww.books-shop.comПодсистема STREAMS373(являющегося обязательным приложением), а затем производится встраива!ние дополнительных модулей для получения требуемой функциональности.Процесс открывает поток с помощью системного вызовапереда!вая ему в качестве аргумента имя специального файла устройства.