Память устройство управления ввод вывод

Обновлено: 06.07.2024

Мы уже обсуждали проблемы организации ввода/вывода в ОС UNIX в п. 2.6.2. В этом разделе мы хотим рассмотреть этот вопрос немного более подробно, разъяснив некоторые технические детали. При этом нужно отдавать себе отчет, что в любом случае мы остаемся на концептуальном уровне. Если вам требуется написать драйвер некоторого внешнего устройства для некоторого конкретного варианта ОС UNIX, то неизбежно придется внимательно читать документацию. Тем не менее знание общих принципов будет полезно.

Традиционно в ОС UNIX выделяются три типа организации ввода/вывода и, соответственно, три типа драйверов. Блочный ввод/вывод главным образом предназначен для работы с каталогами и обычными файлами файловой системы, которые на базовом уровне имеют блочную структуру. В пп. 2.4.5 и 3.1.2 указывалось, что на пользовательском уровне теперь возможно работать с файлами, прямо отображая их в сегменты виртуальной памяти. Эта возможность рассматривается как верхний уровень блочного ввода/вывода. На нижнем уровне блочный ввод/вывод поддерживается блочными драйверами. Блочный ввод/вывод, кроме того, поддерживается системной буферизацией (см. п. 3.3.1).

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

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

Принципы системной буферизации ввода/вывода

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

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

Эта традиционная схема буферизации вошла в противоречие с развитыми в современных вариантах ОС UNIX средствами управления виртуальной памятью и в особенности с механизмом отображения файлов в сегменты виртуальной памяти (см. пп. 2.4.5 и 3.1.2). (Мы не будем подробно объяснять здесь суть этих противоречий и предложим читателям поразмышлять над этим.) Поэтому в System V Release 4 появилась новая схема буферизации, пока используемая параллельно со старой схемой.

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

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

Почему же нельзя отказаться от старого механизма буферизации? Все дело в том, что новая схема предполагает наличие некоторой непрерывной адресации внутри объекта внешней памяти (должен существовать изоморфизм между отображаемым и отображенным объектами). Однако, при организации файловых систем ОС UNIX достаточно сложно распределяет внешнюю память, что в особенности относится к i-узлам. Поэтому некоторые блоки внешней памяти приходится считать изолированными, и для них оказывается выгоднее использовать старую схему буферизации (хотя, возможно, в завтрашних вариантах UNIX и удастся полностью перейти к унифицированной новой схеме).

Системные вызовы для управления вводом/выводом

Для доступа (т.е. для получения возможности последующего выполнения операций ввода/вывода) к файлу любого вида (включая специальные файлы) пользовательский процесс должен выполнить предварительное подключение к файлу с помощью одного из системных вызовов open, creat, dup или pipe. Программные каналы и соответствующие системные вызовы мы рассмотрим в п. 3.4.3, а пока несколько более подробно, чем в п. 2.3.3, рассмотрим другие "инициализирующие" системные вызовы.

  • анализируется непротиворечивость входных параметров (главным образом, относящихся к флагам режима доступа к файлу);
  • выделяется или находится пространство для описателя файла в системной области данных процесса (u-области);
  • в общесистемной области выделяется или находится существующее пространство для размещения системного описателя файла (структуры file);
  • производится поиск в архиве файловой системы объекта с именем "pathname" и образуется или обнаруживается описатель файла уровня файловой системы (vnode в терминах UNIX V System 4);
  • выполняется связывание vnode с ранее образованной структурой file.

Системные вызовы open и creat (почти) функционально эквивалентны. Любой существующий файл можно открыть с помощью системного вызова creat, и любой новый файл можно создать с помощью системного вызова open. Однако, применительно к системному вызову creat мы должны подчеркнуть, что в случае своего естественного применения (для создания файла) этот системный вызов создает новый элемент соответствующего каталога (в соответствии с заданным значением pathname), а также создает и соответствующим образом инициализирует новый i-узел.

Наконец, системный вызов dup (duplicate - скопировать) приводит к образованию нового дескриптора уже открытого файла. Этот специфический для ОС UNIX системный вызов служит исключительно для целей перенаправления ввода/вывода (см. п. 2.1.8). Его выполнение состоит в том, что в u-области системного пространства пользовательского процесса образуется новый описатель открытого файла, содержащий вновь образованный дескриптор файла (целое число), но ссылающийся на уже существующую общесистемную структуру file и содержащий те же самые признаки и флаги, которые соответствуют открытому файлу-образцу.

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

Операция записи выполняется аналогичным образом, но меняет содержимое буфера буферного пула.

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

Наконец, для специальных файлов поддерживается еще один "специальный" системный вызов ioctl. Это единственный системный вызов, который обеспечивается для специальных файлов и не обеспечивается для остальных разновидностей файлов. Фактически, системный вызов ioctl позволяет произвольным образом расширить интерфейс любого драйвера. Параметры ioctl включают код операции и указатель на некоторую область памяти пользовательского процесса. Всю интерпретацию кода операции и соответствующих специфических параметров проводит драйвер.

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

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

Рис. 3.5. Интерфейсы и входные точки драйверов

Блочные драйверы

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

В случае, если копия требуемого блока не находится в буферном пуле или если по какой-либо причине требуется заменить содержимое некоторого обновленного буфера, ядро ОС UNIX обращается к процедуре strategy соответствующего блочного драйвера. Strategy обеспечивает стандартный интерфейс между ядром и драйвером. С использованием библиотечных подпрограмм, предназначенных для написания драйверов, процедура strategy может организовывать очереди обменов с устройством, например, с целью оптимизации движения магнитных головок на диске. Все обмены, выполняемые блочным драйвером, выполняются с буферной памятью. Перепись нужной информации в память соответствующего пользовательского процесса производится программами ядра, заведующими управлением буферами.

Символьные драйверы

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

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

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

Потоковые драйверы

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

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

Устройства делят на две категории (некоторые не попадают ни в одну):

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

символьные устройства - информация считывается и записывается посимвольно (принтер, сетевые карты, мыши)

9.1.2 Контроллеры устройств

Устройства ввода-вывода обычно состоят из двух частей:

механическая (не надо понимать дословно) - диск, принтер, монитор

электронная - контроллер или адаптер

Если интерфейс между контроллером и устройством стандартизован (ANSI, IEEE или ISO), то независимые производители могут выпускать совместимые как контроллеры, так и устройства. Например: диски IDE или SCSI.

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

9.1.3 Отображаемый на адресное пространство памяти ввод-вывод

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

У многих устройств есть буфер данных (например: видеопамять).

Реализации доступа к управляющим регистрам и буферам:

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

смешанная реализация - используется в х86 и Pentium,
от 0 до 64К отводится портам,
от 640 до 1М зарезервировано под буферы данных.


Способы реализации доступа к управляющим регистрам и буферам

9.1.4 Прямой доступ к памяти (DMA - Direct Memory Access)

Прямой доступ к памяти реализуется с помощью DMA - контроллера.

Контроллер содержит несколько регистров:

регистр адреса памяти

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

Без контроллера происходит следующее:

Процессор дает команду дисковому контроллеру прочитать данные в буфер,

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

Контроллер диска инициирует прерывание

Операционная система начинает работать и может считывать из буфера данные в память

Работа DMA - контроллера

С контроллером происходит следующее:

Процессор программирует контроллер (какие данные и куда переместить)

Процессор дает команду дисковому контроллеру прочитать данные в буфер

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

Контроллер DMA посылает запрос на чтение дисковому контроллеру

Контроллер диска поставляет данные на шину, адрес памяти уже находится на шине, происходит запись данных в память

Когда запись закончена, контроллер диска посылает подтверждение DMA контроллеру

DMA контроллер увеличивает используемый адрес и уменьшает значение счетчика байтов

Все повторяется с пункта 4, пока значение счетчика не станет равной нулю.

Контроллер DMA инициирует прерывание

Операционной системе не нужно копировать данные в память, они уже там.

9.1.5 Прерывания

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

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

Контроллер прерываний - обслуживает поступающие прерывания от устройств.

Если необработанных прерываний нет, прерывание выполняется немедленно.

Если необработанных прерываний есть, контроллер игнорирует прерывание. Но устройство продолжает удерживать сигнал прерывания на шине до тех пор, пока оно не будет обработано.

Устройство выставляет сигнал прерывания

Контроллер прерываний инициирует прерывание, указывая номер устройства

Процессор начинает выполнять обработку прерывания, вызывая процедуру

Эта процедура подтверждает получение прерывания контроллеру прерываний

9.2 Принципы программного обеспечения ввода-вывода

9.2.1 Задачи программного обеспечения ввода-вывода

Основные задачи, которые должно решать программное обеспечение ввода-вывода:

Независимость от устройств - например, программа, читающая данные из файла не должна задумываться с чего она читает (CD, HDD и др.). Все проблемы должна решать ОС.

Единообразное именование - имя файла или устройства не должны отличаться. (В системах UNIX выполняется дословно).

Обработка ошибок - ошибки могут быть отловлены на уровне контроллера, драйвера и т.д.

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

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

Три основных способа осуществления операций ввода-вывода:

Управляемый прерываниями ввод-вывод

Ввод-вывод с использованием DMA

Рассмотрим их подробнее.

9.2.2 Программный ввод-вывод

В этом случае всю работу выполняет центральный процессор.

Рассмотрим процесс печати строки ABCDEFGH этим способом.

Этапы печати строки ABCDEFGH

Строка для печати собирается в пространстве пользователя.

Обращаясь к системному вызову, процесс получает принтер.

Обращаясь к системному вызову, процесс просит распечатать строку на принтере.

Операционная система копирует строку в массив, расположенный в режиме ядра.

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

Символ печатается на бумаге.

Указатель устанавливается на следующий символ.

Процессор ждет, когда бит готовности принтера выставится в готовность.

При использовании буфера принтера, сначала вся строка копируется в буфер, после этого начинается печать.

9.2.3 Управляемый прерываниями ввод-вывод

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

Рассмотрим тот же пример, но с небольшим усовершенствованием.

До пункта 8 тоже самое.

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

Когда принтер будет готов, он посылает прерывание процессору.

Процессор переключается на печатающий процесс.

9.2.4 Ввод-вывод с использованием DMA

Недостаток предыдущего метода в том, что прерывание происходит при печати каждого символа.

Алгоритм не отличается, но всю работу на себя берет контроллер DMA.

9.3 Программные уровни и функции ввода-вывода

Четыре уровня ввода-вывода:

9.3.1 Обработчики прерываний

Прерывания должны быть скрыты как можно глубже в недрах операционной системы, чтобы как можно меньшая часть ОС имела с ними дело. Лучше всего блокировать драйвер, начавший ввод-вывод.

Драйвер начинает операцию ввод-вывод.

Обработчик прерываний начинает работу

Обработчик прерываний может разблокировать драйвер (например, выполнив на семафоре процедуру up)

9.3.2 Драйвера устройств

Драйвер устройства - необходим для каждого устройства. Для разных ОС нужны разные драйверы.

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

Это одна из основных причин приводящих к краху операционных систем. Потому что драйверы, как правило, пишутся производителями устройств, и вставляются в ОС.

Логическое расположение драйверов устройств. На самом деле обмен данными между контроллерами и драйверами идет по шине.

Драйвера должны взаимодействовать с ОС через стандартные интерфейсы.

Стандартные интерфейсы, которые должны поддерживать драйвера:

Для блочных устройств

Для символьных устройств

Раньше для установки ядра приходилось перекомпилировать ядра системы.

Сейчас в основном ОС загружают драйверы. Некоторые драйверы могут быть загружены в горячем режиме.

Функции, которые выполняют драйвера:

обработка запросов чтения или записи

управление энергопотреблением устройства

прогрев устройства (сканера)

включение устройства или запуска двигателя

9.3.3 Независимое от устройств программное обеспечение ввода-вывода

Функции независимого от устройств программного обеспечения ввода-вывода:

Единообразный интерфейс для драйверов устройств,

Захват и освобождение выделенных устройств (блокирование)

Размер блока, не зависящий от устройств

Единообразный интерфейс для драйверов устройств

Кроме интерфейса, в него также входят проблемы,

Буферизация

Рассмотрим несколько примеров буферизации.

a) Не буферизованный ввод - после ввода каждого символа происходит прерывание

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

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

d) Двойная буферизация в ядре - если один буфер заполнен, и пока он выгружается, символы пишутся во второй буфер.

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

Захват и освобождение выделенных устройств

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

Независимый от устройств размер блока

Размер блока должен быть одинаковый для верхних уровней, и не зависеть от устройств (размеров секторов на диске).

9.3.4 Программное обеспечение ввода-вывода пространства пользователя

Функции этого обеспечения:

Обращение к системным вызовам ввода-вывода (через библиотечные процедуры).

Форматный ввод-вывод (меняют формат, например, в ASCII)

Спулинг (для выделенных устройств) - создается процесс (например, демон печати) и каталог спулера.

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

Физическая организация устройств ввода-вывода

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

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

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

ОС выполняет ввод-вывод, записывая команды в регистры контроллера. Например, контроллер гибкого диска IBM PC принимает 15 команд, таких как READ, WRITE, SEEK, FORMAT и т.д. Когда команда принята, процессор оставляет контроллер и занимается другой работой. При завершении команды контроллер организует прерывание для того, чтобы передать управление процессором операционной системе, которая должна проверить результаты операции. Процессор получает результаты и статус устройства, читая информацию из регистров контроллера.

Организация программного обеспечения ввода-вывода

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

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

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

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

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

  • Обработка прерываний,
  • Драйверы устройств,
  • Независимый от устройств слой операционной системы,
  • Пользовательский слой программного обеспечения.

Рис. 2.30. Многоуровневая организация подсистемы ввода-вывода

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

Драйверы устройств

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

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

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

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

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

Независимый от устройств слой операционной системы

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

  • обеспечение общего интерфейса к драйверам устройств,
  • именование устройств,
  • защита устройств,
  • обеспечение независимого размера блока,
  • буферизация,
  • распределение памяти на блок-ориентированных устройствах,
  • распределение и освобождение выделенных устройств,
  • уведомление об ошибках.

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

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

Пользовательский слой программного обеспечения

Хотя большая часть программного обеспечения ввода-вывода находится внутри ОС, некоторая его часть содержится в библиотеках, связываемых с пользовательскими программами. Системные вызовы, включающие вызовы ввода-вывода, обычно делаются библиотечными процедурами. Если программа, написанная на языке С, содержит вызов

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

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

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

Контроллеры устройств

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

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

Любое устройство, подключенное к компьютеру, подключается через разъем и розетку, а разъем подключается к контроллеру устройства. Ниже приведена модель подключения ЦП, памяти, контроллеров и устройств ввода-вывода, в которой все ЦП и контроллеры устройств используют общую шину для связи.

Контроллеры устройств

Синхронный и асинхронный ввод-вывод

Связь с устройствами ввода / вывода

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

Специальная инструкция ввода / вывода

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

Отображение в памяти ввода-вывода

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

Отображение в памяти ввода-вывода

При использовании отображения ввода-вывода в память ОС выделяет буфер в памяти и сообщает устройству ввода-вывода использовать этот буфер для отправки данных в ЦП. Устройство ввода-вывода работает асинхронно с ЦП, прерывает ЦП после завершения.

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

Прямой доступ к памяти (DMA)

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

Прямой доступ к памяти (DMA) означает, что ЦП предоставляет полномочия модуля ввода / вывода для чтения или записи в память без участия. Модуль DMA сам управляет обменом данными между основной памятью и устройством ввода-вывода. CPU задействуется только в начале и в конце передачи и прерывается только после того, как весь блок был передан.

Для прямого доступа к памяти требуется специальное оборудование, называемое контроллером DMA (DMAC), которое управляет передачей данных и разрешает доступ к системной шине. Контроллеры запрограммированы с указателями источника и назначения (где для чтения / записи данных), счетчиками для отслеживания количества переданных байтов и настройками, которые включают в себя ввод / вывод и типы памяти, прерывания и состояния для циклов ЦП.

DMA

Операционная система использует оборудование DMA следующим образом:

шаг Описание
1 Драйвер устройства получает указание перенести данные с диска на адрес буфера X.
2 Затем драйвер устройства дает команду контроллеру диска передать данные в буфер.
3 Контроллер диска начинает передачу DMA.
4 Контроллер диска отправляет каждый байт контроллеру DMA.
5 Контроллер DMA передает байты в буфер, увеличивает адрес памяти, уменьшает счетчик C, пока C не станет равным нулю.
6 Когда C становится равным нулю, DMA прерывает CPU, чтобы завершить передачу сигнала.

Опрос против прерывания ввода / вывода

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

Опрос ввода / вывода

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

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

Прерывает ввод / вывод

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

Читайте также: