Реализация драйверов в MS-DOS — КиберПедия 

Кормораздатчик мобильный электрифицированный: схема и процесс работы устройства...

Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...

Реализация драйверов в MS-DOS

2019-09-26 689
Реализация драйверов в MS-DOS 3.75 из 5.00 4 оценки
Заказать работу

Если бы все программы обращались для обмена данными непосредственно к портам периферийных устройств компьютера, программирование превратилось бы в чрезвычайно сложную задачу. В самом деле, во всем мире выпускаются десятки модификаций видеоконтроллеров, принтеров, контроллеров диска и другой аппаратуры, предназначенной для оснащения так называемых "компьютеров, совместимых с IBM PC".

На деле ни о какой полной совместимости на уровне портов ввода/вывода и протоколов обмена данными говорить не приходится. Поэтому, например, вместе с текстовым процессором Microsoft Word for MS-DOS поставляются десятки принтерных драйверов, по одному для каждой модели принтера или семейства моделей принтеров.

Может ли программист учесть все особенности существующей аппаратуры, а также той, что появится в будущем? Очевидно, не может, если, конечно, у него нет дара ясновидения, а также неограниченного запаса времени на тестирование своей программы для бесконечных конфигураций и моделей аппаратного обеспечения. Нам встречалось множество программ, которые могли работать только с той аппаратурой, что имелась в наличии у разработчика. Например, бухгалтерские программы, которые "умели" печатать документы только на принтере Epson FX-850, программы, которые устанавливались только с диска A: емкостью 360 Кбайт и т. д.

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

Все современные операционные системы обращаются к периферийным устройствам через специальные программные модули - драйверы. В таких операционных системах, как Windows NT, OS/2 или UNIX, обычная программа не может вызывать команды ввода/вывода. Для обращения к периферийному устройству она прямо или косвенно (через операционную систему) должна вызвать драйвер.

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

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

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

Использование BIOS как дополнительного интерфейса между драйверами стандартных устройств и аппаратурой резко повышает "живучесть" MS-DOS на персональных компьютерах, не вполне совместимых с IBM PC. И это действительно так - самая распространенная на сегодняшний день операционная система MS-DOS работает на всех компьютерах, хоть сколько-нибудь совместимых с IBM PC.

Это возможно благодаря тому, что производители совместимых компьютеров учитывают в BIOS все аппаратные особенности, и MS-DOS "не видит" отличий. А прикладная программа, работающая с устройством через драйвер, - и подавно.

Тем не менее, BIOS не используется в операционных системах Windows NT, UNIX или OS/2.

Дело в том, что, к сожалению, BIOS не является реентерабельным. Это не имеет значения для однозадачной MS-DOS, но мультизадачные операционные системы вынуждены сами организовывать обслуживание аппаратуры реентерабельным способом. Существуют еще проблемы разделения ресурсов между параллельно работающими процессами, которые тоже не решаются в рамках BIOS.

Пользователи могут легко дополнять операционную систему своими драйверами, составленными для нестандартных устройств. Возможна также замена стандартных драйверов, использование драйверов для замены или расширения функций MS-DOS и BIOS.

 

1. Структура загружаемого драйвера

 

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

Но, оказывается, управляющий блок в самом начале модуля драйвера имеется. Это так называемый заголовок драйвера. Только в отличие от заголовка exe-программ, заголовок драйвера создается не редактором связи, а самим программистом и должен быть помещен в самое начало исходного текста программы-драйвера.

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

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

Не стоит пытаться запускать драйвер как com-программу, так как управление будет передано в область памяти, содержащую заголовок драйвера, а там нет правильных машинных команд. Поэтому обычно файлы драйверов имеют расширения имени, отличные от com или exe. Чаще всего используются расширения sys, drv, иногда bin. На самом деле можно использовать любое расширение имени, так как при описании драйвера в файле config.sys указывается его полное имя.

Для загруженного в память драйвера никогда не создается префикс программного сегмента PSP. В начале исходного текста программы-драйвера не ставится директива ORG 100h (как это делается для com-программы), так как не надо резервировать место для PSP.

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

 

Смещение, байт Размер, байт Имя поля Описание
0 4 next Указатель на заголовок следующего драйвера. Если смещение адреса следующего драйвера равно FFFFh, это последний драйвер в цепочке
4 2 attrib Атрибуты драйвера
6 2 strateg Смещение программы стратегии драйвера
8 2 interrupt Смещение программы обработки прерывания для драйвера
10 8 dev_name Имя устройства для символьных устройств или количество обслуживаемых устройств для блочных устройств

 

Все драйверы связаны в цепочку. Самый первый драйвер находится сразу за векторной таблицей связи. Поле next заголовка драйвера указывает на следующий драйвер (на его заголовок). Это поле имеет формат дальнего указателя и состоит из адреса сегмента и смещения. Признаком того, что данный драйвер является последним в цепочке, служит значение 0FFFFh в компоненте смещения поля next.

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

 

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

Обычно исходный текст программы содержит один драйвер, и поле next задается следующим образом:

 

next DD 0FFFFFFFFh

 

Следующее поле в заголовке драйвера - поле атрибутов драйвера atrib.

Это поле описывает устройство, которое обслуживает драйвер. Каждый бит слова отвечает за ту или иную особенность устройства. Прежде чем мы детально рассмотрим назначение всех бит этого слова, заметим, что бит 15 (самый старший бит) указывает, является ли это устройство символьным или блочным.

Следует специально отметить, что все драйверы можно разделить на две группы - драйверы символьных устройств и драйверы блочных устройств. Первые обслуживают устройства символьного ввода/вывода, такие как принтеры, клавиатура, последовательные адаптеры и т. д., вторые ориентированы на обмен данных блоками - это драйверы дисковых устройств.

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

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

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

Мы рассмотрим драйверы обоих типов, при этом мы каждый раз будем отмечать особенности символьных и блочных устройств.

Приведем назначение отдельных битов слова атрибутов символьного драйвера:

 

Бит Назначение
0 1 - драйвер обслуживает стандартное устройство ввода; 0 - этот драйвер не обслуживает стандартное устройство ввода
1 1 - драйвер обслуживает стандартное устройство вывода; 0 - драйвер не обслуживает стандартное устройство вывода
2 1 - драйвер стандартного устройства NUL; 0 - драйвер не обслуживает устройство NUL
3 1 - драйвер обслуживает часы
4 Для работы с устройством можно использовать средство быстрого символьного вывода - прерывание INT 29h. Это прерывание предназначено для быстрого вывода символа на консоль, код символа необходимо записать в регистр AL
5 Зарезервировано, бит должен быть равен 0
6 1 - разрешено использование драйвером функций IOCTL; 0 - функции IOCTL не поддерживаются
7 1 - устройство может принимать запросы IOCTL (интерфейс IOCTL будет описан позже)
8-10 Эти биты зарезервированы и должны быть равны 0
11 1 - поддерживаются функции открытия/закрытия устройства (OPEN/CLOSE); 0 - функции OPEN/CLOSE для символьных устройств не поддерживаются
12 Зарезервировано, бит должен быть равен 0
13 1 - для символьных устройств поддерживается функция вывода до получения состояния занятости устройства; 0 - функция вывода до состояния занятости не поддерживается
14 1 - поддерживаются функции чтения и записи через интерфейс IOCTL; 0 - функции чтения/записи через интерфейс IOCTL не поддерживаются
15 1 - символьное устройство; 0 - блочное устройство

 

Для драйверов блочных устройств формат слова атрибутов другой:

 

Бит Назначение
0 Зарезервировано, бит должен быть равен 0
1 1 - драйвер поддерживает 32-битовую адресацию сектора (для MS-DOS версии 4.00 и более поздних версий).Если установлен этот бит, поле номера сектора всех запросов является двойным словом, добавляемым в конец заголовка запроса, старое поле номера сектора должно содержать -1; 0 - используется 16-битовая адресация сектора
2-5 Эти биты зарезервированы и должны быть равны 0
6 1 - поддерживаются логические дисковые устройства; 0 - логические устройства не поддерживаются
7 1 - устройство может принимать запросы
8-10 Эти биты зарезервированы и должны быть равны 0
11 1 - единица в этом бите означает, что драйвер поддерживает функцию проверки замены носителя данных в устройстве (например, замены дискеты); 0 - функция проверки замены носителя данных не поддерживается
12 Зарезервировано, бит должен быть равен 0
13 1 - драйверу необходимо выдать запрос на построение блока параметров BIOS BPB (для выполнения этого запроса драйвер считывает сектор логического диска, содержащий начало таблицы FAT, в этом секторе находится байт идентификации носителя данных); 0 - запрос не требуется, драйвер пользуется FAT
14 1 - поддерживаются функции чтения и записи через интерфейс IOCTL; 0 - функции чтения/записи через интерфейс IOCTL не поддерживаются
15 1 - символьное устройство; 0 - блочное устройство

 

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

 

attrib DW 8000h

 

После слова атрибутов драйвера находятся два очень важных поля: смещение программы стратегии драйвера strateg и смещение программы обработки прерывания interrupt. Эти две программы используются MS-DOS для организации вызова драйвера.

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

Задача программы стратегии - запомнить этот адрес внутри тела драйвера для дальнейшего использования или организовать очередь запросов обслуживания.

Сразу после вызова программы стратегии MS-DOS вызывает программу обработки прерываний, определив ее адрес из поля interrupt заголовка драйвера.

Программа обработки прерывания извлекает только что записанный программой стратегии адрес заголовка запроса и выполняет ту функцию, номер которой записан в запросе. Номер функции находится в заголовке запроса. Результаты выполнения функции программа прерывания записывает в специально отведенные поля заголовка запроса, после чего процедура обращения MS-DOS к драйверу завершается.

Формат заголовка запроса будет приведен ниже, а сейчас покажем, как в заголовке драйвера задаются смещения программ стратегии и прерывания:

 

strateg DW strateg_proc

interrupt DW interrupt_proc

 

Последнее поле заголовка драйвера dev_name имеет различную интерпретацию для символьных и блочных устройств.

 

Для символьных устройств в этом поле должно располагаться имя устройства, выровненное по левому краю. Если длина имени меньше 8 байт, его нужно дополнить пробелами. Это имя будет использоваться для обращения к драйверу. Если вы собираетесь заменить драйвер стандартного символьного устройства MS-DOS на свой, нужно записать имя устройства прописными буквами:

 

dev_name DB 'AUX '

 

Для блочных устройств первый байт поля dev_name содержит количество устройств, обслуживаемых данным драйвером, остальные семь байт не используются:

 

dev_name DB 1

              DB 7 dup(?)

 

Таким образом, мы выяснили, что драйвер содержит в самом начале заголовок, и где-то дальше должны располагаться программы стратегии и прерывания. Не следует путать программу прерывания драйвера с программой обслуживания аппаратных или программных прерываний. Хотя программа прерывания драйвера немного похожа на обработчик программных прерываний, назначение этой программы и механизм ее использования совершенно другой.

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

На длину драйвера накладывается такое же ограничение, как и на длину com-программ - 64 Кбайт, то есть один сегмент.

 

2. Процесс загрузки драйверов

 

Системный файл MS-DOS с именем io.sys содержит драйверы для некоторых устройств. Эти драйверы появляются в памяти при загрузке операционной системы и связаны в цепочку через поля next в своих заголовках. Такие драйверы мы будем называть резидентными драйверами MS-DOS.

Резидентные драйверы можно заменить драйверами пользователя. Кроме того, пользователь может добавить в список драйверов новые.

Для подключения драйвера к операционной системе файл config.sys должен содержать строку следующего вида:

 

DEVICE=<путь_файла_драйвера>_<параметры>.

 

Например:

 

DEVICE=c:\dos\smartdrv.sys 120

 

В этом примере подключается драйвер smartdrv.sys, который находится в каталоге dos на диске C:. В качестве параметра инициализации драйверу передается число 120. Параметры считываются драйвером один раз в процессе инициализации драйвера.

Загружаемые дополнительно драйверы находятся в списке драйверов перед резидентными драйверами.

Для каждого драйвера выводится адрес его расположения в памяти, слово атрибутов драйвера и имя устройства (либо количество обслуживаемых блочным драйвером устройств).

Первым в этом списке всегда является драйвер устройства с именем NUL. Это так называемое нуль-устройство, которое можно использовать для отладки. Драйвер псевдоустройства NUL не может быть переназначен, он всегда расположен непосредственно за векторной таблицей связи MS-DOS.

Дальше идут драйверы, описанные в файле config.sys.

Начиная с драйвера консоли CON, в списке расположены резидентные драйверы, имеющие сегментный адрес 0070. Это драйвер последовательного канала связи AUX, драйвер устройства печати PRN, драйвер часов CLOCK$, драйверы последовательных каналов COM1, COM2, COM3, COM4 и драйверы устройств печати LPT1, LPT2, LPT3.

Если ваш драйвер должен заменить стандартный, укажите имя устройства заглавными буквами (например, LPT1). Система разместит ваш драйвер в цепочке драйверов до стандартного драйвера с именем LPT1.

Когда операционная система загружает драйвер, она создает заголовок запроса и помещает в него команду инициализации. Затем она вызывает программу стратегии драйвера, которой передается адрес подготовленного заголовка запроса. После этого управление передается программе прерывания драйвера. Эта программа просматривает заголовок запроса и выполняет указанную в ней команду инициализации.

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

Более подробно процесс инициализации будет рассмотрен при описании команды инициализации драйвера.

 

 

3. Связь драйвера с операционной системой

 

После загрузки драйвер становится как бы частью операционной системы. Все обращения к драйверу MS-DOS выполняет с использованием заголовка драйвера.

Перед обращением к драйверу MS-DOS готовит заголовок запроса в своей внутренней области данных и вызывает программу стратегии, извлекая ее смещение из заголовка драйвера. Программа стратегии обычно очень проста, так как все, что она должна сделать, это запомнить адрес заголовка запроса в области памяти драйвера.

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

 

Приведем формат заголовка запроса:

 

Смещение, байт Размер, байт Имя поля Описание
0 1 size Общий размер блока запроса в байтах (длина заголовка запроса плюс длина переменной части запроса)
1 1 unit Номер устройства. Используется для блочных устройств; указывает, с каким именно устройством (из числа обслуживаемых данным драйвером) будет работать операционная система
2 1 cmd Код команды, которую требуется выполнить. Может иметь значение от 00h до 18h
3 2 status Слово состояния устройства. Заполняется драйвером перед возвращением управления операционной системе
5 8 reserved Зарезервировано

 

После вызова программы стратегии MS-DOS передает управление программе прерывания (без параметров). Задача программы прерывания - выполнить команду, код которой находится в поле cmd заголовка запроса. Если драйвер блочного устройства обслуживает несколько логических устройств, то в поле unit находится номер устройства, для которого необходимо выполнить команду.

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

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

 

Приведем формат слова состояния устройства:

 

Бит Назначение
0-7 Код ошибки устройства. Если команда выполнена с ошибкой и драйвер установил признак ошибки (бит 15) в единицу, он должен записать в это поле код ошибки
8 Команда выполнена. Этот бит всегда устанавливается драйвером перед возвращением управления операционной системе
9 Занято. Этот бит устанавливается обработчиком команды, когда физическое устройство занято выполнением предыдущей операции и поэтому не может выполнить новую команду. Данный бит используется также для передачи информации о том, что буфер клавиатуры содержит данные или о том, что среда носителя данных может быть заменена (в команде проверки возможности замены среды носителя данных)
10-14 Зарезервировано
15 Признак ошибки. Устанавливается драйвером, когда он не может обработать запрос или произошла физическая либо логическая ошибка при обработке правильного запроса. Биты 0-7 при этом должны содержать код ошибки

 

Приведем таблицу кодов ошибок:

 

Код Описание
0 Нарушение защиты от записи. Была предпринята попытка записи информации на защищенное от записи устройство
1 Неизвестное устройство
2 Устройство не готово
3 Неизвестная команда. Данная команда не поддерживается драйвером
4 Ошибка CRC. При выполнении команды обнаружена ошибка в контрольной сумме
5 Неправильная длина запроса. Поле длины в заголовке запроса содержит неверное значение
6 Ошибка при поиске дорожки (дорожка не найдена)
7 Неизвестный носитель данных
8 Сектор не найден
9 В принтере нет бумаги
0Ah Ошибка записи
0Bh Ошибка чтения
0Ch Общая ошибка
0Dh Зарезервировано
0Eh Зарезервировано
0Fh Замена диска не разрешается

 

Общая схема действий программы прерывания драйвера такова:

 

· получив управление от операционной системы, программа прерывания сохраняет содержимое всех регистров процессора и считывает номер команды из заголовка запроса;

· при необходимости программа считывает дополнительную информацию из области запроса;

· затребованная команда выполняется (если она поддерживается драйвером);

· если драйвер считывает какие-либо данные от физического устройства для передачи их операционной системе, то программа прерывания записывает эти данные или их адреса в область запроса;

· программа прерывания устанавливает слово состояния устройства в соответствии с результатами выполнения команды (если драйвер не поддерживает затребованную команду, в слове состояния устройства устанавливаются биты 15 и в биты 0-7 записывается код ошибки 3 - неизвестная команда);

· программа прерывания восстанавливает содержимое регистров процессора, вслед за чем управление возвращается операционной системе (с помощью команды возврата из дальней процедуры).

 

4. Драйвер системных часов CLOCK$

 

Операционная система содержит в своем составе драйвер системных часов. Это драйвер символьного устройства, имя устройства - CLOCK$.

Символ "$" используется для того, чтобы это имя не конфликтовало с именем файла clock. Дело в том, что пользователь может создать файл с именем clock, но с именем clock$ - едва ли (разве лишь он пожелает закодировать в этом имени фразу "время - деньги").

Характерный признак драйвера системных часов - бит 3 слова атрибутов устройства установлен в 1. Именно этот признак используется MS-DOS для обнаружения драйвера часов.

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

 

 

Смещение Длина Назначение
0 2 Количество дней, прошедших после 1 января 1980 года
2 1 Счетчик минут
3 1 Счетчик часов
4 1 Счетчик сотых долей секунды
5 1 Счетчик секунд

 

5. Особенности отладки драйверов

 

 

Драйверы достаточно сложны для отладки. На этапе инициализации драйвера (при выполнении команды инициализации) загрузка операционной системы еще не завершена, и воспользоваться обычным отладчиком невозможно. Отладчик Turbo Debugger позволяет вам отлаживать драйверы в режиме удаленной отладки, но для этого потребуется второй компьютер.

Прикладная программа не вызывает драйвер напрямую, а делает это через функции прерывания MS-DOS, поэтому вам придется очень долго "добираться" до программы прерывания драйвера. Малейшие ошибки в программе инициализации могут привести к невозможности завершения загрузки операционной системы.

Программа стратегии обычно очень проста и проблем не вызывает.

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

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

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


Реализация потоков в MS-DOS

Ввод/вывод в операционных системах (как MS-DOS, так и UNIX) может быть организован двумя принципиально разными способами. Первый способ - это прямое программирование устройств ввода/вывода (дисковода, экрана, модема, клавиатуры). Он может быть организован на различных уровнях (непосредственное программирование устройств, использование сервисных средств операционной системы, смешанный подход и т.д.), но суть его при этом не меняется. Каждая программа, написанная с использованием этого способа, может работать только с этим устройством и ни с каким другим. В настоящее время используется именно этот способ. Именно с помощью этого подхода (точнее, путем "косвенного" программирования периферийных устройств через драйверы этих устройств) и реализован классический WIMP - интерфейс, о котором уже было много сказано в предыдущей главе. Он позволяет создавать красивые и довольно содержательные средства общения с пользователем (меню, окна и тому подобное), а современные технологии позволяют программе при установке автоматически настраиваться на установленное на компьютере оборудование. Но у этих систем есть недостаток: они не могут принять данные с устройств и передать данные устройствам, для работы с которыми они не созданы. Например, нельзя данные вводить с модема, если программа работает только с клавиатурой. Чтобы осуществить это, используют другой способ: ввод/вывод с использованием потоков. В этом случае каждое устройство рассматривается операционной системой как файл, куда можно поместить и откуда можно взять информацию. Так же, как информация, записанная в файл, рассматривается операционной системой как единое целое, не зависимо от способа записи его на диске, так и физическая реализация процесса ввода/вывода информации устройством никак не отражается на работе пользователя.

 

Ограничение потоков.

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

 

Определение и классификация потоков.

Поток, скажем так, представляет собой некоторый буфер в памяти, куда поступает или откуда выбирается информация. Существуют следующие стандартные потоки:

1. Стандартный поток ввода - это обычно клавиатура.

2. Стандартный поток вывода - это обычно монитор.

3. Стандартный поток вывода ошибок и диагностических сообщений (стандартный поток ошибок) - это обычно дисплей (монитор).

 

Переназначение потоков.

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

 

> переназначает стандартный поток вывода другому устройству (или файлу). Если этот файл существует, он очищается, и на его место записывается новая информация. Используется в DOS и UNIX. В UNIX те же действия может осуществлять конструкция 1>
>> То же самое, но если файл существует, то новая информация записывается в конец этого файла. Используется в DOS и UNIX. Для UNIX также можно использовать конструкцию 1>>

 

Переназначение стандартного потока ошибок (в UNIX).

Обычными средствами DOS не может перенаправить стандартный поток ошибок. В UNIX для этого можно использовать команды 2> и 2>>, соответствующие вышеприведенным для стандартного потока вывода.

Для перенаправления в UNIX стандартного потока ошибок в стандартный поток вывода используется конструкция >$ (по умолчанию в UNIX стандартному потоку ввода присваивается номер 0, стандартному потоку вывода - 1, а стандартному потоку ошибок - 2. Конструкция в UNIX 0 >$ 2 переназначает стандартный поток ввода в стандартный поток ошибок, то есть все символы, введенные в этом сеансе с клавиатуры, тут же отображаются на экране, и их нельзя перенаправить в файл).

 

Перенаправление потока ввода.

Переадресация стандартного ввода осуществляется конструкцией < для DOS и UNIX и 0> только для UNIX.

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

program < indata.dat >> outdata.txt

В данном примере входные данные программы program читаются из файла indata.dat и записываются в файл outdata.txt.

В примере:

sort < mylist > prn

данные из файла mylist сортируются стандартной программой MS-DOS sort и результат выводится на принтер.

 

Конвейерная обработка.

Символы переадресации очень удобны, но иногда бывает необходимо организовать последовательность программ, выполняющих обработку информации, причем результат редыдущей программы является исходным для следующей. При этом промежуточные данные желательно никуда не записывать. Чтобы организовать такую обработку, используют знак '|' конвейера. Команды-"цепочки" такой обработки данных просто записываются в одну строку в порядке их вызова для обработки данных, и отделяются одна от другой знаком конвейера '|'. Пример:

sort < mylist | more.

В этом примере данные из файла mylist сортируются программой sort и постранично выводятся на экран программой more.

В UNIX тоже возможна переадресация потока с одновременным выводом данных на экран, и даже переадресация на два разных устройства. Для переадресации стандартного вывода в файл с одновременной выдачей информации на экран используется команда tee. Например, команда cat в UNIX позволяет просматривать файл. Следующая конструкция:

cat first | tee second

копирует файл first в файл second, одновременно показывая его на экране.

 

Перенаправление вывода на принтер.

Для вывода данных на принтер используются конструкции:

в DOS > prn в UNIX lpr

Еще один пример: команда

cat first | tee second | lpr

копирует файл first в файл second, одновременно распечатывая его на принтере.

Командой lpr можно также вывести несколько файлов на печать. Подробности смотри ниже.

 

История возникновения потоков в MS-DOS.

Исторически первая версия MS-DOS основывалась на многоплатформенной операционной системе для восьмиразрядных процессоров - CP/M. От нее она унаследовала и способ работы с файлами - через контрольные блоки файлов (File Control Block, FCB). Но уже во второй версии MS-DOS стала использоваться позаимствованная из операционной системы UNIX работа с файлами через дескрипторы файлов (File Handle). Одновременно с реализацией метода дескрипторов файла в MS-DOS из UNIX перешел поточный механизм организации файлов и возможность перенаправления потоков. с тех пор работа с файлами через FCB стала анахронизмом и поддерживается в операционных системах фирмы Microsoft (вплоть до Windows 98) лишь для совместимости со старыми версиями.

Следует также отметить, что термины "FCB", "дескрипторы файлов", "потоки" употребляются применительно к интерфейсу операций ввода/вывода операционных систем, а не для файловых систем как таковых. Так, использование для работы с файлами метода дескрипторов может происходить и в операционной системе MS-DOS с файловой системой FAT, и в Windows 2000 с NTFS, и в Novell NetWare с NWFS, и в Linux


Поделиться с друзьями:

Индивидуальные очистные сооружения: К классу индивидуальных очистных сооружений относят сооружения, пропускная способность которых...

История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...

Кормораздатчик мобильный электрифицированный: схема и процесс работы устройства...

Типы оградительных сооружений в морском порту: По расположению оградительных сооружений в плане различают волноломы, обе оконечности...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.125 с.