ОСиС_2008
.pdf7. Подсистема ввода-вывода |
247 |
2)b6 — флаг ошибки. Его установка говорит о том, что при выполнении последней операции ввода-вывода произошла ошибка. Нулевое содержимое этого бита сообщает об отсутствии ошибки;
3)b4–b5 используются для задания номера устройства. Таким образом, эти биты являются и битами состояния, и битами управления.
Сделано или устройство готово
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ошибка |
|
Номер устройства |
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
b7 |
b6 |
|
b5 |
|
b4 |
b3 |
b2 |
b1 |
b0 |
Разрешение прерывания
Функция
Разрешение работы
Рис. 60. Пример регистра состояния и управления RS
7.5.1. Двухуровневый драйвер с опросом
Реализацию данного драйвера рассмотрим на следующем гипотетическом примере. Пусть требуется разработать драйвер для управления работой считывателя перфоленты. Допустим, что файлустройство, соответствующий требуемому считывателю перфоленты, имеет имя /dev/pl3. Структура RS приведена на рис. 60. Код вводимого символа помещается в RD.
На рис. 61 приведена логическая схема драйвера. Она представляет собой совокупность трех интерфейсных логических процедур: «Открыть», «Чтение строки байт», «Опрос». Кроме того, эта схема включает две внутренние структуры данных: а) совокупность буферов чтения устройств; б) массив флагов открытия устройств. Рассмотрим работу этих модулей драйвера во взаимодействии с другими аппаратными и программными модулями.
Работа со специальным файлом (файлом-устройством) начинается с открытия этого файла в программе процесса с помощью системного вызова
ОТКРЫТЬ_ФАЙЛ_УСТРОЙСТВА ( /dev/pl3 || i).
248 |
Одиноков В.В., Коцубинский В.П. |
Процесс
ЧТЕНИЕ_ФАЙЛА_УСТРОЙСТВА (i, A, n || )
|
(i, A, n ) ( A, n, ma, mi) |
|
|||
Интерфейс |
Управление |
||||
|
ФС |
|
|||
системных |
|
драйверами |
вызовов |
mi |
( A, n, mi) |
|
|
|
|
|
||
Ядро ОС |
Открыть |
|
Чтение |
|
|
|
строки |
|
|
Обработчик |
Fmi |
|
Буферmi |
|
прерываний |
|
|
|
|
таймера |
|
|
Драйвер П/Л |
|
|
Опрос |
|||
Прерывание |
b0 |
b4–b5 |
b7 |
RD |
|
|
|
|
|
таймера |
|
Управление |
|
|
|
Fu |
|
||
|
устройством |
|
||
|
|
|
||
|
Контроллер |
|
|
|
Рис. 61. Логическая структура драйвера с опросом:
i — программный номер файла-устройства; A — начальный адрес прикладного буфера; n — число читаемых байтов; ma — старший номер устройства; mi — младший номер устройства; Fmi — флаг открытия mi-го устройства; b0 — бит RS разрешения работы; b4–b5 — номер устройства; b7 — бит готовности в RS; RD — буферный регистр данных;
Fu — флаг запуска устройства
Данный вызов преобразуется интерфейсом системных вызовов в команду для виртуальной ФС, которая начинает выполнять открытие файла обычным образом. При этом проверяются права доступа к файлу и создаются необходимые записи в системных таблицах. Специальная реальная ФС находит в inode файла его атрибуты — старший и младший номера устройства. Эти числа
7. Подсистема ввода-вывода |
249 |
используются при формировании команды ФС для модуля управления драйверами.
Используя старший номер устройства, модуль управления находит в коммутаторе строковых драйверов вход в драйвер чтения
сперфоленты и находит в этом входе строку с адресом процедуры «Открыть». При вызове данной процедуры ей на вход передается параметр — младший номер устройства.
Процедура «Открыть» проверяет установку флага открытия, соответствующего устройству с номером mi. Так как устройство ввода с перфоленты является последовательно используемым (см. подразд. 2.3), то оно не может быть открыто более одного раза.
Поэтому если флаг Fmi установлен, то процедура «Открыть» блокирует вызывающий процесс (переводит в состояние «Сон»).
Если же флаг Fmi сброшен, то процедура «Открыть» устанавливает этот флаг и запускает требуемое устройство, установив в 1 b0, записав перед этим в b4–b5 номер устройства mi. Каждая запись в бит b0 приводит к копированию его содержимого во флаг Fu, который управляет работой одного из устройств. Кроме того,
процедура «Открыть» сбрасывает бит RS b3, запрещая тем самым прерывания от устройства ввода с перфоленты, которые в данном драйвере не используются.
Как показано на рис. 61, упрощенная логическая структура контроллера представляет собой совокупность логических процессов, каждый из которых предназначен для управления одним устройством. В состоянии бездействия такой процесс находится в своей точке входа, ожидая установки своего управляющего флага
Fu. Установка этого флага приводит к тому, что контроллер включает двигатель устройства, обеспечивающий перемотку перфоленты на один шаг. После этого очередной байт переписывается
сперфоленты в буферный регистр данных RD. (Каждый байт хранится на перфоленте в виде восьми отверстий (битов), расположенных перпендикулярно направлению ленты.) Кроме того, логический процесс контроллера записывает номер своего устройства
в биты b4–b5 RS, а также производит установку бита готовности b7. После этого данный логический процесс возвращается в точку своего входа.
Запустив устройство, процедура «Открыть» возвращает управление в модуль управления драйверами. Дальнейший возврат управления продолжится по цепочке модулей и завершится возвратом в прикладную программу процесса. При этом в качестве параметра будет передан программный номер i файла-устройства.
250 |
Одиноков В.В., Коцубинский В.П. |
Допустим, что через некоторое время процесс передал в ядро системный вызов для чтения требуемого числа байтов n с перфоленты:
ЧТЕНИЕ_ФАЙЛА_УСТРОЙСТВА (i, A, n || ).
Подобно обычным файлам, ФС находит inode файла, а затем использует его для определения номеров устройства ma и mi. Эти номера используются, в свою очередь, для выдачи запроса к модулю управления драйверами. Этот модуль находит требуемый вход в коммутаторе строковых драйверов и вызывает из этого входа процедуру «Чтение строки байтов».
Данная процедура выбирает из множества буферов драйвера тот буфер, который соответствует заданному номеру mi. Если количество символов, находящихся в этом буфере, не менее требуемого числа n, то первые n символов извлекаются из буфера драйвера и записываются в прикладную область памяти процесса с заданным начальным адресом A. Напомним, что модули верхнего уровня драйвера, как и модули ядра, соединяющие процесс с драйвером, выполняются в контексте этого процесса. Это обеспечивает данным модулям доступ не только к памяти ядра, но и к прикладной памяти процесса. После завершения записи в прикладную область памяти управление возвращается в прикладную часть процесса — на машинную команду, расположенную сразу же за командой системного вызова.
Если на момент выполнения процедуры «Чтение строки байтов» буфер драйвера не содержит требуемого числа символов, то данная процедура перепишет имеющиеся в буфере символы в прикладную область процесса, а затем выполнит блокирование текущего процесса, переводя его в состояние «Сон». Разблокирование процесса произойдет позже, когда процедура «Опрос» или обнаружит наличие в буфере недостающего числа символов, или обнаружит, что буфер полон. В любом случае выполнение процесса продолжится с процедуры «Чтение строки байтов», которая не только перепишет недостающие символы из буфера драйвера в прикладную область, но и выполнит включение устройства (установкой бита b0).
Основной функцией процедуры «Опрос» является прием символов, читаемых устройствами ввода с перфоленты и записываемых затем контроллером в регистр RD. Данная процедура инициируется через постоянные промежутки времени обработчиком прерываний таймера (обычно через тик) и выполняется в контексте этого обработчика, не имея никакого доступа к прикладной памя-
7. Подсистема ввода-вывода |
251 |
ти текущего процесса. При каждом инициировании процедура «Опрос» переписывает символ из RD в буфер драйвера. Если после записи символа в буфер окажется, что буфер полон, то данная процедура выключает устройство (сбросом бита b0).
Так как процедуры «Чтение строки байтов» и «Опрос» работают с общими структурами данных, выполняясь в контексте разных процессов, то они не только кооперируются, но и конкурируют из-за этих структур данных и нуждаются в синхронизации (см. п. 2.4.3). Подобная синхронизация обеспечивается запретом на время выполнения процедуры «Чтение строки байтов» всех маскируемых прерываний (в том числе от таймера).
7.5.2. Двухуровневый драйвер с прерыванием на байт
Основная идея построения драйверов на основе использования сигналов прерывания заключается в том, чтобы информация о завершении устройством текущей операции ввода-вывода поступала в драйвер не по инициативе драйвера, то есть в результате опроса, а по инициативе самого устройства (или его ИУ). Рассмотрим реализацию такого драйвера опять на примере управления гипотетическим устройством ввода с перфоленты.
Логическая схема драйвера представляет собой активный пакет, состоящий из двух интерфейсных логических процедур, логического процесса и двух структур данных (рис. 62). Работа модулей верхнего уровня драйвера мало отличается от работы соответствующих модулей в драйвере с опросом. Отличия заключаются в том, что процедура «Открыть» не сбрасывает, а, наоборот, устанавливает бит разрешения прерываний b3.
Что касается нижнего уровня драйвера, то образующий этот уровень обработчик прерываний инициируется сигналом прерывания, поступившим в ЦП из контроллера ввода с перфоленты. Этот сигнал прерывания поступает на вход обработчика в виде управляющего воздействия через коммутатор строковых драйверов (вход драйвера «обработка прерывания») или через дескрипторную таблицу прерываний IDT (см. п. 5.4.3). Второй из этих вариантов инициирования обработчиков прерываний реализуется в большем числе систем. После своего инициирования обработчик прерываний переписывает код символа из RD в буфер драйвера и, если
252 |
|
Одиноков В.В., Коцубинский В.П. |
|||
буфер не полон, устанавливает бит запуска устройства b0 и бит |
|||||
разрешения прерываний b3. Иначе эти биты сбрасываются. |
|
||||
|
Процесс |
|
|
|
|
ЧТЕНИЕ_ФАЙЛА_УСТРОЙСТВА (i, A, n || ) |
|
||||
Интерфейс |
(i, A, n ) |
( A, n, ma, mi) |
Управление |
||
системных |
|
ФС |
|
драйверами |
|
вызовов |
|
mi |
|
|
|
|
|
|
( A, n, mi) |
|
|
|
|
Открыть |
|
Чтение строки |
|
|
|
|
|
байт |
|
|
|
Fmi |
|
Буферmi |
|
|
|
Fmi |
|
Буферmi |
|
|
|
Fmi |
|
Буферmi |
|
|
Драйвер П/Л |
Обработчик |
|
||
|
прерываний |
|
|||
Ядро ОС |
|
|
|
|
|
|
|
b0 |
b4–b5 |
RD |
b3 |
|
|
bb0 0 |
Управление 2 |
2 |
|
|
|
Fu |
устройством |
|
|
|
Контроллер |
|
|
|
|
Рис. 62. Логическая структура драйвера с прерыванием: |
|
||||
i — программный номер файла-устройства; A — начальный адрес |
|||||
прикладного буфера; n — число читаемых байтов; |
|
||||
ma — старший номер устройства; mi — младший номер устройства; |
|||||
Fmi — флаг открытия mi-го устройства; b0 — бит RS разрешения работы; |
|||||
b3 — бит разрешения прерываний в RS; b4–b5 — номер устройства; |
|||||
RD — буферный регистр данных; Fu — флаг запуска устройства |
7. Подсистема ввода-вывода |
253 |
Как и для драйвера с опросом, логическая схема контроллера представляет собой совокупность логических процессов, каждый из которых выполняет управление одним устройством. Если устройство не работает, его управляющий процесс находится в состоянии «Вход 1», ожидая установки флага запуска устройства Fu. Значение b0 = 1 приводит к установке этого флага для устройства с заданным номером, что инициирует работу контроллера по вводу очередного символа. Логический процесс контроллера помещает код символа в RD (сбрасывая при этом бит b0 RS)
иоказывается в состоянии «вход 2». Так как бит разрешения прерывания b3 = 1, то контроллер инициируется по данному входу
ивыдает сигнал прерывания. Обработчик прерываний считывает код символа из RD в буфер драйвера. Если при этом буфер оказывается полным, то управление сразу возвращается прерван-
ной программе. Иначе сначала установкой b0 = 1 инициируется работа контроллера по вводу следующего символа.
В рассмотренном изложении предполагалось, что аппаратный сигнал внешнего прерывания поступает от ИУ сразу в ЦП. Но
вбольшинстве ВС такие сигналы поступают сначала в програм-
мируемый контроллер прерываний. Данный контроллер упоря-
дочивает поступление сигналов внешних прерываний в ЦП.
Вкачестве примера рассмотрим контроллер прерываний i8259A. Данный контроллер имеет 8 входов — IRQ0, IRQ1…IRQ7, позволяющих принимать запросы на прерывание от восьми ИУ:
IRQ0 — таймер; IRQ1 — клавиатура;
IRQ2 — второй контроллер прерываний; IRQ3 — последовательный порт COM2; IRQ4 — последовательный порт COM1; IRQ5 — параллельный порт LPT2; IRQ6 — гибкий диск;
IRQ7 — параллельный порт LPT1.
Данные входы имеют приоритеты: чем меньше номер входа, тем приоритет выше. Поэтому самыми приоритетными являются сигналы прерываний от таймера. Приоритет сигнала используется контроллером прерываний для определения возможности направления этого сигнала в ЦП. При этом если в контроллер одновременно поступило несколько сигналов прерываний, то из них
вЦП будет отправлен тот сигнал, приоритет которого выше. Кроме того, если ЦП уже занят обработкой какого-то прерывания, то
254 |
Одиноков В.В., Коцубинский В.П. |
новый сигнал будет отправлен контроллером прерываний только в том случае, если его приоритет выше, чем у того прерывания, обработчик которого выполняется на ЦП.
Номер прерывания, соответствующий конкретному ИУ, можно определить следующим образом: к базовому номеру, соответствующему контроллеру прерываний (8), следует прибавить номер входа в этот контроллер. Например, номер прерывания от клавиа-
туры: N = 8 + 1 = 9.
Как и любое ИУ, контроллер прерываний имеет порты, которые используются программами (драйверами) для управления им. Эти порты имеют адреса 20h и 21h. Порт 21h используется, в частности, для маскирования (то есть для запрета) прерываний от устройств требуемого типа. Для этого требуется записать единицу в тот бит порта, который соответствует номеру входа для устройства. Например, следующие две команды выполняют маскирование прерываний от клавиатуры:
mov |
AL, 00000010b ; Вход для клавиатуры — IRQ1 |
out |
21h, AL |
Существуют другие команды управления контроллером прерываний, позволяющие размаскировать прерывания от любого ИУ (независимо от маскирования в ЦП), а также изменять приоритеты ИУ. Аналогичные команды используются и для управления вторым (ведомым) контроллером прерываний, который подсоединяется к входу IRQ2 ведущего контроллера. Поэтому ИУ, обслуживаемые ведомым контроллером, выдают сигналы прерываний с приоритетами, расположенными между приоритетами клавиатуры и последовательного порта COM2. Для управления ведомым контроллером используются порты A0h и A1h, аналогичные портам 20h и 21h для ведущего контроллера. Базовый номер прерываний, соответствующий ведомому контроллеру прерываний, равен 70h.
В заключение приведем два типа устройств, обслуживаемых ведомым контроллером прерываний (с указанием его входов):
IRQ13 — математический сопроцессор;
IRQ14 — жесткий магнитный диск.
Благодаря коммутаторам драйверов любая вышестоящая система (ФС, дисковый КЭШ или подсистема управления памятью) имеет стандартный интерфейс для доступа к любым драйверам. Допускается построение строчно-блоковых драйверов, имеющих свои записи в обоих коммутаторах. Поведение такого драйвера
7. Подсистема ввода-вывода |
255 |
(а точнее — используемый набор интерфейсных процедур) зависит от того, через какой коммутатор был сделан доступ к драйверу.
7.5.3. Блочные драйверы с прямым доступом в память
Основное отличие блочных и строковых драйверов заключается в том, как они выполняют обслуживание поступающих запросов на ввод-вывод данных. Строковые драйверы используют для этого две отдельные интерфейсные процедуры «Чтение строки байт» и «Запись строки байт», каждая из которых использует отдельный буфер-очередь драйвера для размещения символьных строк, обслуживаемых в порядке поступления. Каждый блочный драйвер использует для обслуживания поступающих запросов на ввод-вывод данных единственную интерфейсную процедуру «Чте- ние-запись блока», которая помещает все запросы в единственную очередь (рис. 63), элементами которой являются дескрипторы буферов блоков, предназначенных для вывода на устройство или читаемых с него. При этом отметим, что блоковый драйвер не имеет собственного буфера, так как в качестве буферов блоков используются или элементы буфера КЭШа (см. п. 6.4.2), или физические страницы ОП (см. п. 5.3.1).
Вызов процедуры «Чтение-запись блока» происходит следующим образом: дисковый КЭШ или подсистема управления памятью вызывает процедуру «Управление драйверами», передав ей на вход единственный параметр — указатель на дескриптор буфера блока. Этот дескриптор содержит детали требуемой операции информационного обмена с устройством. Структура дескриптора буфера блока была рассмотрена нами в п. 6.4.2. Одно из полей этой структуры содержит старший номер устройства и используется модулем управления драйверами для поиска требуемой точки входа в коммутаторе блочных драйверов. Далее модуль управления драйверами инициирует процедуру «Чтение-запись блока» в требуемом драйвере, передав ей указатель на дескриптор буфера блока.
Процедура «Чтение-запись блока» начинает свое выполнение с того, что помещает новый запрос в очередь на обслуживание. Элементами этой очереди являются дескрипторы буферов блоков. (Напомним, что два поля в каждом дескрипторе представляют собой указатели на соседние элементы очереди.) Далее процедура «Чтение-запись блока» выбирает один элемент из очереди и при-
256 |
Одиноков В.В., Коцубинский В.П. |
ступает к его обслуживанию. При этом важно подчеркнуть, что выборка запросов из очереди производится не в порядке поступления, а в соответствии с некоторой стратегией эффективности. При этом под эффективностью обычно понимается общее время выполнения всех заявок в очереди, и, следовательно, целесообразно выбирать заявки из «очереди» в таком порядке, при котором данное время будет минимальным. Указанное общее время зависит в основном от времени перемещения головок дисковода между
цилиндрами диска. Поэтому целесообразно сначала выполнить чте-
От дискового КЭШа, или
ние илиот подсистемызапись блокауправленияна соседнемпамятьюцилиндре, а уж затем обрабатывать далеко расположенный блок, несмотря на то что соот-
ветствующаяКоммутаторзаявка, блочныхвозможно, поступила гораздо раньше.
драйверов
. . . . . |
|
|
|
|
открыть |
|
|
|
|
закрыть |
|
|
|
|
чтение-запись |
|
|
|
|
блока |
u |
|
|
|
обработка |
|
|
ер |
|
прерывания |
|
|
||
. . . . . |
Очередь |
|
Буфер |
|
(A, v, n) |
|
|||
|
|
|||
Открыть |
Чтение- |
|
Подготовка |
|
|
запись блока |
|
ПДП |
|
Драйвер дисковода |
|
|
|
|
К |
|
|
|
|
диспетчеру |
Обработчик |
Драйвер |
|
|
|
прерываний |
|
||
|
ПДП |
|
||
Прерывание |
RS1 |
|
|
RS2 |
|
|
|
|
|
Контроллер |
2 |
Канал |
2 |
|
дисковода |
ПДП |
1 |
||
|
|
|
||
|
Контроллер ПДП |
|