Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ОСиС_2008

.pdf
Скачиваний:
96
Добавлен:
29.05.2015
Размер:
2.65 Mб
Скачать

7. Подсистема ввода-вывода

237

Драйверы

Верхний

 

 

 

 

Блочный

 

 

 

 

Строковый

 

 

 

интерфейс

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Тип

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Блочное

 

 

Символьное

 

 

 

Псевдоустройство

устройства

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Число

Одноуровневый

 

 

Двухуровневый

 

 

 

уровней

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Многоуровневый

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Тип

 

 

Общая

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

память

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

синхрони-

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Прерывание

 

зации

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

на байт

 

 

 

Прямой доступ

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

в память

 

 

Опрос

 

 

 

 

 

 

 

 

 

Рис. 56. Классификация драйверов

Процедуры двухуровнего драйвера делятся на две группы: процедуры верхнего уровня драйвера и процедуры нижнего уровня драйвера. Подобно одноуровневому драйверу, процедуры верхнего уровня выполняются в контексте процесса, выдавшего системный вызов. А процедуры нижнего уровня драйвера инициируются или обработчиком прерываний от управляемого устройства, или обработчиком прерываний таймера. При этом процедуры разных уровней никак не связаны между собой по управлению. Если требуется информационное взаимодействие между уровнями, то для его реализации используются общие структуры данных (буферы).

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

238

Одиноков В.В., Коцубинский В.П.

В качестве последнего признака классификации драйверов будем использовать тип синхронизации между программой драйвера и управляемой им аппаратурой (ПУ + ИУ). Сущность этой синхронизации состоит в следующем. Любой драйвер должен выполнять три основных функции взаимодействия с ПУ:

1)подготовка ПУ и, возможно, самого драйвера к последующим операциям по обмену данными — выполнение команды «Открыть устройство»;

2)инициирование очередной операции ПУ по вводу (выводу) единицы информации;

3)обеспечение завершения очередной операции ввода-вывода. Первые две функции выполняются модулями верхнего уровня

драйвера в контексте того процесса, в интересах которого выполняется информационный обмен с ПУ. Что касается третьей функции, то она выполняется нижним уровнем драйвера в контексте ядра, недоступном для процессов. Реализация этой функции зависит от типа используемой синхронизации.

Существуют типы синхронизации: опрос; прерывание на байт; прямой доступ в память; общая память. Разница между этими типами синхронизации заключается в том, как «узнает» программа драйвера о завершении текущей операции информационного обмена с ПУ. В методе опроса это делает само ядро, периодически опрашивая состояние устройства. В методе прерываний на байт это делает ИУ, выдавая в ЦП сигнал прерывания по завершению периферийным устройством очередной операции ввода-вывода байта данных. В методе прямого доступа в память сигнал прерывания выдается в ЦП при завершении ввода-вывода не одного байта, а целого блока данных. Использование общей памяти для управления устройством делает синхронизацию на программном уровне между драйвером и ПУ вообще ненужной.

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

7. Подсистема ввода-вывода

239

7.3. Аппаратный интерфейс

Несмотря на то что конструкция драйвера в значительной степени определяется типом ПУ, фактическое взаимодействие драйвера происходит не с ПУ, а с его ИУ. Поэтому остановимся на вопросе интерфейса между этими модулями. Допустим, что ЭВМ имеет структуру с общей шиной (см. рис. 1). С помощью одного ИУ к ОШ подсоединяется или одно, или несколько однотипных ПУ. Простейшее ИУ состоит из одного или более регистров, в состав которых обязательно входит регистр состояния и управления RS. Этот регистр играет для ИУ и подключенных к нему ПУ ту же роль, что регистр EFLAGS играет для ЦП, то есть фактически является их блоком управления.

Количество регистров состояния и управления, а также назначение их битов для разных ИУ существенно отличаются. Биты этого регистра (регистров) делятся на управляющие биты и биты состояния. Управляющие биты устанавливаются программами, которые исполняются на ЦП, и предназначены для задания режима работы ПУ. Примером управляющих битов являются биты функции, используемые для уточнения операции (функции), выполняемой устройством.

Биты состояния устанавливаются ПУ или его ИУ. Их назначение заключается в том, чтобы сообщить программе ЦП (драйверу) о текущем состоянии ПУ. Примером бита состояния является флаг ошибки. Его установка говорит о том, что при выполнении последней операции ввода-вывода произошла ошибка. Нулевое содержимое этого бита сообщает об отсутствии ошибки.

Кроме RS многие ИУ имеют буферный регистр данных (RD),

предназначенный для временного хранения одного или двух байтов данных, передаваемых на ПУ при выводе или принимаемых с ПУ при вводе.

При использовании простейшего ИУ всю работу по управлению ПУ выполняет сам ЦП. При этом он отвлекается от выполнения самих программ, в результате чего значительно снижается его фактическая производительность. Применение более сложных ИУ позволяет возложить на них значительную часть работы по управлению ПУ, которая теперь, в принципе, может выполняться параллельно работе ЦП. Наиболее сложным ИУ является контроллер — специализированный процессор вводавывода. (Как и всякое ИУ, контроллер имеет свои RS и RD.)

240

Одиноков В.В., Коцубинский В.П.

Регистры ИУ, непосредственно доступные из программ ЦП, называются портами. Портами являются многие RS и RD (но не все), а также служебные регистры, используемые для программного доступа к тем RS и RD, к которым нет непосредственного доступа. Каждый порт в ЭВМ имеет свой уникальный номер, называемый адресом порта. Для некоторых типов ЦП программные операции с портами (чтение и запись) выполняются точно так же, как и операции с ячейками ОП. При этом для адресации портов используется часть адресного пространства ОП, в которой каждый реальный адрес соответствует не ячейке ОП, а порту.

Для процессоров Intel используется другой подход, при котором существуют два адресных пространства — одно для ячеек ОП, а второе — для портов. При этом адрес порта — число в диапазоне от 0 до 65535, а сам порт представляет собой 8-битный регистр. Следствием наличия двух адресных пространств является использование для работы с портами специальных команд ЦП: in — для ввода из порта и out — для вывода в порт.

7.4. Одноуровневые драйверы

Особенностью одноуровнего драйвера является то, что все его процедуры выполняются в контексте того процесса, который выдал системный вызов для работы с устройством, обслуживаемым данным драйвером. Использование такой простой структуры объясняется возможностью непосредственного доступа программ ЦП к внутренней памяти ИУ благодаря отображению этой памяти на виртуальное адресное пространство ОП. Такая непосредственная передача информации между ИУ и прикладной памятью процесса делает ненужным использование промежуточных буферов и, как следствие, исключает потребность промежуточного копирования. К сожалению, ИУ лишь немногих устройств, к которым относятся различные экраны (мониторы), допускают отображение своей внутренней памяти на ОП.

Допустим, что для вывода на экран строк символов программы процессов используют системные вызовы записи в специальные файлы /dev/mnj, где j — номер экрана. В этом случае для управления экранами в текстовом режиме может использоваться драйвер, упрощенная логическая схема которого приведена на рис. 57. (Используемое при этом упрощение заключается в том, что в действительности портом ИУ экрана является не RS (а точнее, несколько RS), а два других, специально предназначенных для

7. Подсистема ввода-вывода

241

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

Логическая схема на рис. 57 представляет собой совокупность двух интерфейсных (то есть доступных для вызова извне драйвера) логических процедур «Открыть», «Запись строки байт». Кроме того, эта схема включает внутреннюю структуру данных — массив, каждый элемент которого представляет собой текущие координаты курсора для одного из экранов. Рассмотрим работу этих модулей драйвера во взаимодействии с другими аппаратными и программными модулями.

 

 

 

 

Процесс

 

ЗАПИСЬ_ФАЙЛ_УСТРОЙСТВА (i, A, n || )

 

 

 

 

 

( A, n, ma, mi)

 

 

 

(i, A, n )

 

 

Интерфейс

 

 

ФС

Управление

системных

 

 

 

драйверами

 

 

 

 

 

 

 

вызовов

 

 

 

 

mi

 

 

 

 

 

( A, n, mi)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Открыть

 

Запись

 

 

строки байт

 

 

FFmimi

 

Ядро ОС

 

XT , YT

Драйвер

 

 

 

 

 

RS

 

Видеопамять

 

 

 

 

Аппаратно

Видеоадаптер

Контроллер

 

Рис. 57. Логическая структура драйвера экрана:

i — программный номер файла-устройства; A — начальный адрес прикладного буфера; n — число выводимых байтов; ma — старший номер устройства; mi — младший номер устройства; RS — регистр состояния и управления; XT , YT — текущие координаты курсора

242

Одиноков В.В., Коцубинский В.П.

Подобно работе с обычными файлами, работа со специальным файлом (файлом-устройством) начинается с открытия этого файла в программе процесса. Для этого может использоваться, например, следующий системный вызов:

ОТКРЫТЬ_ФАЙЛ_УСТРОЙСТВА ( /dev/mn3 || i).

Данный вызов преобразуется интерфейсом системных вызовов в команду для виртуальной ФС, которая начинает выполнять открытие файла обычным образом. При этом проверяются права доступа к файлу и создаются необходимые записи в системных таблицах. Так как файл специальный, то для работы с ним привлекается специальная реальная ФС. Эта ФС находит в inode файла его атрибуты — старший и младший номера устройства. Далее эти числа используются при формировании команды ФС для модуля управления драйверами.

Используя старший номер устройства, модуль управления драйверами находит в коммутаторе строковых драйверов вход в драйвер экрана и в этом входе находит строку с адресом процедуры «Открыть». При вызове данной процедуры ей на вход передается младший номер устройства.

Процедура «Открыть» начинает с того, что выполняет отображение видеопамяти требуемого экрана на область памяти ядра. При этом видеопамяти каждого экрана соответствует своя отдельная область. В п. 6.1.3 рассматривалось отображение на память ядра областей ВП по запросам прикладных программ. Несмотря на то что реализация отображения видеопамяти имеет существенные отличия, она преследует ту же цель — обеспечить работу программы (драйвера) с видеопамятью точно так же, как с обычной ОП. В частности, полученное отображение видеопамяти используется самой процедурой «Открыть» для того, чтобы заполнить экран символами пробела с требуемым цветом фона.

Далее процедура «Открыть» по заданному номеру устройства mi находит адрес порта RS требуемого экрана (каждый экран имеет свой RS) и выполняет запись в его биты управления с целью: 1) задания номера дисплейной страницы (этот термин будет пояснен позже), выводимой на экран; 2) задания первоначальных координат курсора; 3) задания формы курсора. Курсор — светящийся прямоугольник, генерируемый аппаратно. Обычно курсор указывает на ту позицию экрана, в которую будет помещен следующий символ, выводимый на экран. Но так как положение курсора и вывод символов на экран никак не связаны аппаратно, то син-

7. Подсистема ввода-вывода

243

хронизацией между ними должен заниматься сам драйвер. Выполнив первоначальную установку курсора, процедура «Открыть» по-

мещает его первоначальные координаты в переменные XT и YT . Видеопамять, а также контроллер экрана входят в состав ИУ

экрана, называемого видеоадаптером, в качестве примера которого мы будем рассматривать видеоадаптер CGA. Являясь одним из первых видеоадаптеров (создан в 1981 году), CGA имитируется аппаратно многими другими, более современными видеоадаптерами. Видеопамять в CGA имеет размер 16 кбайтов. Каждый символ занимает в ней два байта. В младшем из этих байтов содержится код ASCII символа (информация о том, что выводить), а в старшем байте — атрибуты символа (информация о том, как выводить). Структура байта атрибутов приведена на рис. 58. Задавая в байте атрибутов комбинации битов красного, зеленого и синего цветов, а также интенсивности, можно получить другие цвета, например сиреневый (R = 1, G = 0, B = 1, I = 0) или желтый (R = 1,

G = 1, B = 0, I = 1).

7

6

5

 

4

3

2

1

 

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

R

 

G

 

B

I

 

R

 

G

 

B

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Цвет фона

 

 

 

 

 

Цвет символа

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Мерцание

 

 

 

 

Интенсивность

 

 

 

 

 

 

 

 

 

 

 

R — красный

 

 

 

 

 

 

 

 

 

 

 

G — зеленый

 

 

 

 

 

 

 

 

 

 

 

B — синий

 

 

 

 

 

 

 

 

 

Рис. 58. Структура байта атрибутов

На экране одновременно могут находиться 2000 символов (80*25). Эти символы занимают 4000 байтов (около 4 кбайтов) видеопамяти. Такая область памяти, занимаемая данными для вывода экрана, называется дисплейной страницей. Нетрудно подсчитать, что в видеопамяти CGA объемом 16 кбайтов могут разместиться 4 дисплейных страницы. При этом данные экрана располагаются в памяти построчно (начиная с верхнего левого угла), а небольшие пустоты между страницами усекаются аппаратно.

244

Одиноков В.В., Коцубинский В.П.

Аппаратура адаптера периодически считывает содержимое видеопамяти (а точнее — дисплейной страницы) и помещает его на экран. Электронный луч, управляемый системой отклонения, пробегает по экрану строка за строкой слева направо и сверху вниз (развертка). При этом контроллер включает и выключает интенсивность луча, повторяя «узор» битов в видеопамяти. За секунду электронный луч 50 раз пробегает по всему экрану (кадру). Между кадрами луч должен из правого нижнего угла вернуться в левый верхний угол. Это движение называется обратным ходом луча.

Запустив устройство (экран), процедура «Открыть» возвращает управление в модуль управления драйверами. Дальнейший возврат управления продолжится по цепочке модулей и завершится возвратом в прикладную программу процесса. При этом в качестве параметра будет передан программный номер i файла-устройства.

Допустим, что через некоторое время процесс передал в ядро системный вызов для вывода требуемого числа байтов n из своей прикладной области на экран:

ЗАПИСЬ_ФАЙЛ_УСТРОЙСТВА (i, A, n || ).

Подобно обычным файлам, ФС находит inode файла, а затем использует его для определения номеров устройства ma и mi. Эти номера используются, в свою очередь, для выдачи запроса к модулю управления драйверами. Этот модуль находит требуемый вход в коммутаторе строковых драйверов и вызывает из этого входа процедуру «Запись строки байтов».

Данная процедура находит по заданному номеру mi отображение видеопамяти требуемого экрана, а затем переписывает в область отображения заданную строку символов из прикладной памяти процесса, помещая между записываемыми символами байты атрибутов. При этом для определения начального адреса в области отображения используются текущие координаты курсора XT и YT. После завершения записи в видеопамять процедура «Запись строки байтов» корректирует содержимое этих переменных, а также изменяет расположение курсора на экране, выполнив корректировку RS. После завершения данной процедуры управление возвратится в прикладную программу на команду, следующую за командой системного вызова для вывода на экран.

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

7. Подсистема ввода-вывода

245

7.5. Двухуровневые драйверы

На рис. 59 приведена укрупненная двухуровневая структура строкового драйвера.

от ФС

Коммутатор

 

 

 

 

строковых драйверов

 

 

 

 

 

. . . . .

 

 

 

 

 

открыть

 

 

 

 

 

закрыть

 

 

 

 

 

чтение устройства

 

 

 

 

 

запись на устройство

 

 

 

 

 

опрос устройства

 

 

 

 

 

обработка прерывания

 

 

 

 

 

. . . . .

 

 

 

 

 

 

Модули верхнего

Драйвер

 

прерывание

уровня

 

 

от драйвера

 

 

 

 

таймера

чтение

запись

 

 

 

 

 

 

 

Модули

 

 

 

нижнего уровня

 

 

 

 

 

Аппаратный

 

 

 

 

интерфейс

 

 

 

ИУ

 

 

 

 

ПУ1

ПУК

 

Рис. 59. Укрупненная структура строкового драйвера

 

Данная структура включает программные модули верхнего уровня: 1) «Открыть устройство»; 2) «Закрыть устройство»; 3) «Чтение с устройства»; 4) «Запись на устройство»; модули нижнего уровня: 1) «Опрос устройства»; 2) «Обработчик прерываний». Причем модули разных уровней никак не связаны между собой по

246

Одиноков В.В., Коцубинский В.П.

управлению. Они взаимодействуют только через общие структуры данных — буфер чтения и буфер записи. Эти буферы реализуются как очереди, элементами которых являются или вводимые/ выводимые символы, или области памяти фиксированной длины, содержащие эти символы. В первом случае буфер реализуется в виде несвязанной, а во втором — в виде связанной очереди.

Несмотря на то что модули обоих уровней относятся к ядру, они работают с различным объемом линейной виртуальной памяти. Модули верхнего уровня имеют дело со всеми 4 Гбайт ЛВП, так как они выполняются в контексте процесса. Поэтому они могут выполнять перенос данных между прикладными буферами (находятся в прикладной части ЛВП) и буферами драйвера (в системной части ЛВП). Модули нижнего уровня работают только с 1 Гбайт системной части ЛВП.

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

На рис. 60 приведен пример типичного RS, который будет использоваться нами в дальнейшем. В этом RS биты b0–b5 — управляющие биты, устанавливаемые программами ЦП:

1)если b0 = 1, то разрешается работа ПУ по вводу (выводу) единицы информации;

2)b1b2 используются для уточнения операции (функции), выполняемой устройством;

3)если b3 = 1, то в ЦП может быть выдан сигнал прерывания;

4)b4b5 используются для задания номера устройства.

На рис. 60 биты b4–b7 — биты состояния ПУ, устанавливаемые ПУ или его ИУ:

1) b7 описывает состояние буферного регистра данных. Для устройства ввода b7 = 1 означает, что RD заполнен данными, которые могут быть перенесены в ЦП. Для устройства вывода это означает, что выходной буфер данных сейчас пуст и ждет, когда ЦП загрузит в него новые данные;