Иллюстрированный самоучитель по теории операционных систем

Асинхронный ввод-вывод

В системах семейства Unix драйверы блочных устройств обязательно асинхронные. Кроме того, в современных версиях системы асинхронными драйверами являются драйверы потоковых устройств. Многие другие ОС, в том числе однозадачные (такие, как DEC RT-11), используют исключительно асинхронные драйверы.

Драйвер, использующий асинхронную архитектуру, обычно предоставляет вместо отдельных функций read, write, ioctl и т. д. единую функцию, которая в системах семейства Unix называется strategy, а мы будем называть стратегической функцией (рис. 10.7).

Иллюстрированный самоучитель по теории операционных систем › Драйверы внешних устройств › Асинхронный ввод-вывод
Рис. 10.7. Стратегическая функция и очередь запросов

Запросы к драйверу в VMS

В операционной системе VAX/VMS драйвер получает запросы на ввод-вывод из очереди запросов. Элемент очереди называется IRP (lnput[Output] Request Packet – пакет запроса ввода-вывода). Обработав первый запрос в очереди, драйвер начинает обработку следующего. Операции над очередью запросов выполняются специальными командами процессора VAX и являются атомарными. Если очередь пуста, основная нить драйвера завершается. При появлении новых запросов система вновь запустит ее.

IRP содержит:

  • код операции (чтение, запись или код SPFUN– специальная функция, подобная ioctl в системах семейства Unix);
  • адрес блока данных, которые должны быть записаны, или буфера, куда данные необходимо поместить;
  • информацию, используемую при постобработке, в частности, идентификатор процесса, запросившего операцию.

В зависимости от кода операции драйвер запускает соответствующую подпрограмму. В VAX/VMS адрес подпрограммы выбирается из таблицы FDT (Function Definition Table). Подпрограмма инициирует операцию и приостанавливает процесс, давая системе возможность исполнить другие активные процессы. Затем, когда происходит прерывание, его обработчик инициирует fork-процесс, исполняющий следующие этапы этого запроса. Завершив один запрос, fork-процесс сообщает об этом процедурам постобработки (разбудив соответствующий процесс) и, если в очереди еще что-то осталось, начинает исполнение следующего запроса.

В качестве параметра стратегическая функция получает указатель на структуру запроса, в которой содержатся код требуемой операции и блок данных. При этом возникает сложный вопрос, а именно – в каком адресном пространстве размещается этот блок?

На первый взгляд, идеальным решением было бы размещение этого блока сразу в пользовательском адресном пространстве. Проблема здесь в том, что стратегическая функция – особенно при обработке не первого запроса в очереди – исполняется не в пользовательском контексте, когда можно применять примитивы обмена данными с адресным пространством задачи,в контексте fork-процесса, а то и в контексте прерывания, когда адресное пространство пользователя не определено.

Возможны два варианта решения этой проблемы: хранить в структуре запроса иноке и указатель на пользовательское адресное пространство, либо все-таки копировать данные в адресное пространство системы на этапе предобработки, и обратно в пользовательское на этапе постобработки запроса. Драйвер в этом случае не должен беспокоиться ни о каком копировании, зато разработчик ОС получает дополнительную головную боль в виде логики управления буферами в адресном пространстве системы и выделения памяти для них.

Буферизация запросов и формирование очереди к блочным устройствам в Unix осуществляется специальным модулем системы, который называется дисковым кэшем. Принцип работы дискового кэша будет обсуждаться в разд. "Дисковый кэш". Очереди запросов к потоковым устройствам имеют меньший объем, поэтому выделение памяти для них осуществляется обычным kmalloc.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.