Произвольный и последовательный метод доступа
Устройства ввода/вывода можно грубо разделить на две категории: блочные и символьные. Блочными называются устройства, хранящие информацию в виде адресуемых блоков фиксированного размера. Важное свойство блочного устройства состоит в том, что каждый блок может быть прочитан независимо от остальных блоков(т.е произвольным образом).
Жесткий диск является блочно адресуемым устройством, так как вне зависимости от текущего положения головки дисковода всегда можно переместить ее на определенный цилиндр и затем считать или записать отдельный блок с нужной дорожки.
Как известно, накопители на магнитных дисках обладают крайне низкой скоростью по сравнению с быстродействием центральной части компьютера. Разница в быстродействии отличается на несколько порядков. Например, современные процессоры за один такт работы, а они работают уже с частотами в 1 ГГц и более, могут выполнять по две операции. Таким образом, время выполнения операции (с позиции внешнего наблюдателя, не видящего конвейеризации при выполнении машинных команд, благодаря которой производительность возрастает в несколько раз) может составлять 0,5 нс. В то же время переход магнитной головки с дорожки на дорожку составляет несколько миллисекунд. Такие же временные интервалы имеют место и при ожидании, пока под головкой чтения/ записи не окажется нужный сектор данных. Как известно, в современных приводах средняя длительность на чтение случайным образом выбранного сектора данных составляет около 20 мс, что существенно медленнее, чем выборка команды или операнда из оперативной памяти и уж тем более из кэша. Правда, после этого данные читаются большим пакетом. Таким образом, средняя скорость работы процессора с оперативной памятью на 2-3 порядка выше, чем средняя скорость передачи данных из внешней памяти на магнитных дисках в оперативную память.
Многие контроллеры, особенно контроллеры блок-ориентированных устройств, поддерживают прямой доступ к памяти — DMA (Direct Memory Access). Чтобы понять, как работает DMA, познакомимся сначала с тем, как происходит чтение с диска в отсутствие DMA. Сначала контроллер считывает с диска блок (один или несколько секторов) последовательно, бит за битом, пока весь блок не окажется во внутреннем буфере контроллера. Затем контроллер проверяет контрольную сумму, чтобы убедиться, что при чтении не произошло ошибки. После этого контроллер инициирует прерывание. Когда операционная система начинает работу, она может прочитать блок диска побайтно или пословно, в цикле сохраняя считанное слово или байт в оперативной памяти.
Естественно, цикл, байт за байтом считывающий данные с контроллера, расходует процессорное время. Чтобы освободить процессор от низкоуровневой работы, и был изобретен прямой доступ к памяти. При использовании DMA процедура совершенно другая. Сначала центральный процессор программирует DMA-контроллер, устанавливая его регистры и указывая, таким образом, какие данные и куда следует переместить (рис. 3.2). Затем процессор дает команду дисковому контроллеру прочитать данные во внутренний буфер и проверить контрольную сумму. Когда данные получены и проверены контроллером диска, устройство DMA может начинать работу.
Рис. 3.2. Работа DMA-контроллера
DMA-контроллер начинает перенос данных, посылая дисковому контроллеру по шине запрос на чтение. Этот запрос выглядит как обычный запрос чтения, потому контроллер диска даже не знает, поступил ли он от центрального процессора или от контроллера DMA. Обычно адрес памяти уже находится на адресной шине, соответственно, контроллер диска всегда в курсе, куда нужно переслать следующее слово из своего внутреннего буфера. Запись в память является еще одним стандартным циклом шины. Когда запись закончена, контроллер диска также по шине посылает сигнал подтверждения контроллеру DMA. Затем контроллер DMA увеличивает используемый адрес памяти и уменьшает значение счетчика байтов. После этого шаги со 2-го по 4-й повторяются, пока значение счетчика не станет равно нулю. По завершении цикла копирования контроллер DMA инициирует прерывание процессора, сообщая ему таким образом, что перенос данных завершен. Операционной системе не нужно копировать блок диска в память. Он уже находится там.
Как мы уже упоминали, до начала операции прямого доступа к памяти диск предварительно считывает данные в свой внутренний буфер. Возможно, вы задаетесь вопросом, почему контроллер не помещает данные прямо в оперативную память, по мере получения их с диска. Другими словами, зачем ему нужен внутренний буфер? Тому две причины. Во-первых, при помощи внутренней буферизации контроллер диска может проверить контрольную сумму до начала переноса данных в память. Если значения не совпадают, формируется сигнал об ошибке и перенос данных не производится.
Во-вторых, дело в том, что как только началась операция чтения с диска, биты начинают поступать с постоянной скоростью, независимо от того, готов контроллер диска их принимать или нет. Если контроллер диска попытается писать эти данные напрямую в память, ему придется делать это по системной шине. Если при передаче очередного слова шина окажется занятой каким-либо другим устройством (например, использующим ее в пакетном режиме), контроллеру диска придется ждать. Если следующее слово с диска прибудет раньше, чем контроллер успеет сохранить отложенное, контроллер либо потеряет предыдущее слово, либо ему придется запоминать его где-либо еще. Таким образом, необходимость внутренней буферизации становится очевидной. При наличии внутреннего буфера контроллеру диска шина не нужна до тех пор, пока не начнется операция DMA. В результате устройство контроллера диска оказывается проще, так как при операции прямого доступа к памяти параметр времени не является критичным. (Некоторые древние контроллеры действительно напрямую обращались к памяти, обладая внутренним буфером небольшого размера, что часто приводило к ошибкам перегрузки при занятости шины.)
Описанная выше двухэтапная процедура буферизации имеет важные последствия, касающиеся производительности ввода/вывода. Когда данные передаются от контроллера в память самим контроллером или центральным процессором, под дисковой головкой проходит следующий сектор данных, биты которого поступают в контроллер. Простые контроллеры не умели одновременно считывать и передавать данные, и сектор пропускался.
Как следствие, может быть прочитан любой другой сектор, кроме следующего, а для чтения всей дорожки необходимы два полных оборота диска. Если же время, требуемое для передачи сектора данных в память, превышает время считывания сектора, может потребоваться пропуск двух (или более) блоков.
DMA используется не во всех компьютерах. Главный аргумент против прямого доступа к памяти: центральный процессор обычно значительно превосходит DMA-контроллер по скорости и в состоянии выполнить ту же работу значительно быстрее (если только скорость ограничена не быстродействием устройства ввода/вывода). При отсутствии другой нагрузки у центрального процессора заставлять быстрый центральный процессор ждать, пока медленный контроллер DMA выполнит свою работу, бессмысленно. Кроме того, компьютер без контроллера DMA, с центральным процессором, выполняющим все программно, оказывается дешевле, что крайне важно в производстве компьютеров нижней ценовой категории.
Другой тип устройств ввода/вывода — символьные устройства. Символьное устройство принимает или предоставляет поток символов без какой-либо блочной структуры. Оно не является адресуемым и не выполняет операцию поиска. Принтеры, сетевые интерфейсные адаптеры, мыши (для указания точки на экране), крысы (для лабораторных экспериментов по психологии) и большинство других устройств, не похожих на диски, можно рассматривать как символьные устройства.
Для символьно-ориентированных устройств, таких, как терминалы и принтеры, требуется иная форма буферизации. Информация либо записывается в очередь символов устройством ввода-вывода и считывается процессом, либо записывается процессом и считывается устройством. Символы из очереди могут быть считаны только один раз; прочитанный из очереди символ уничтожается. В этом и состоит отличие от буфера кэша, где процедура чтения может выполняться неоднократно. Поскольку обмен информацией у терминалов относительно медленный, они обычно используют очередь символов. Линии связи также требуют последовательной передачи байтов данных и лучше всего обрабатываются с использованием очередей символов. И, наконец, тип ввода-вывода для принтера, вообще говоря, будет зависеть от его скорости. Медленнодействующие принтеры обычно используют очередь символов» в то время как быстродействующий принтер может воспользоваться небуферизированным вводом-выводом. Для скоростных принтеров в принципе возможно использование кэша. Однако в силу того что данные, поступающие на принтер, никогда не используются повторно, в использовании кэша нет никакого смысла.
Потоки ввода-вывода.
Любая операция ввода/вывода имеет своей целью передать поток данных от одного устройства вычислительной системы другому, которое занимается необходимой обработкой этих, выше указанных, данных. В общем случае все драйверы устройств ввода/вывода могут быть условно разделены по характеру потоков ввода/вывода на два больших класса: блок-ориентированные (block-oriented) и байт-ориентированные (character-oriented). Например, драйверы графических устройств и драйверы сетевых устройств относятся к классу байт-ориентированных.
Блок-ориентированные драйверы управляют устройствами прямого доступа, которые хранят информацию в блоках фиксированного размера, каждый из которых имеет собственный адрес. Самое распространенное внешнее устройство прямого доступа — диск. Адресуемость блоков приводит к тому, что для устройств прямого доступа появляется возможность кэширования данных в оперативной памяти и это обстоятельство значительно влияет на общую организацию ввода-вывода для блок-ориентированных драйверов.
Устройства, с которыми работают байт-ориентированные драйверы, не адресуемы и не позволяют производить операцию поиска данных, они генерируют или потребляют последовательности байт. Примерами таких устройств, которые также называют устройствами последовательного доступа, служат терминалы, строчные принтеры, сетевые адаптеры.
Блок- или байт-ориентированность является характеристикой как самого устройства, так и драйвера. Очевидно, что если устройство не поддерживает обмен адресуемыми блоками данных, а позволяет записывать или считывать последовательность байт, то и устройство, и его драйвер можно назвать байт-ориентированными. Для байт-ориентированного устройства невозможно разработать блок-ориентированный драйвер. Устройство прямого доступа с блочной адресацией является блок-ориентированным, и для управления им естественно использовать блок-ориентированный драйвер. Однако блок-ориентированным устройством можно управлять и с помощью байт-ориентированиого драйвера. Так, диск можно рассматривать не только как набор блоков, но и как набор байт, первый из которых начинает первый блок диска, а последний завершает последний блок. Физический обмен с контроллером устройства по-прежнему осуществляется блоками, но байт-ориентированный драйвер устройства будет преобразовывать блоки в последовательность байт. Для устройств прямого доступа часто разрабатывают пару драйверов, чтобы к устройству можно было обращаться и по байт-ориентированному, и по блок-ориентированному интерфейсам в зависимости от потребностей.
Деление всех драйверов на блок-ориентированные и байт-ориентированные оказывается полезным для структурирования подсистемы управления вводом-выводом. Тем не менее, необходимо учитывать, что эта схема является упрощенной — имеются внешние устройства, драйверы которых не относятся ни к одному классу, например таймер, который, с одной стороны, не содержит адресуемой информации, а с другой стороны, не порождает потока байт. Это устройство только выдает сигнал прерывания в некоторые моменты времени.
Операционная система UNIX в свое время сделала еще один важный шаг по унификации операций и структуризации программного обеспечения ввода-вывода. В ОС UNIX все устройства рассматриваются как некоторые виртуальные (специальные) файлы, что дает возможность использовать общий набор базовых операций ввода-вывода для любых устройств независимо от их специфики. Эти вопросы обсуждаются в следующем разделе, посвященном файлам и файловым системам.
Специальные файлы, называемые иногда виртуальными, не связаны со статичными наборами данных, хранящихся на дисках, а являются удобным унифицированным представлением устройств ввода-вывода.
Понятие специального файла появилось в операционной системе UNIX- Специальный файл всегда связан.с некоторым устройством ввода/вывода и представляет его для остальной части операционной системы и прикладных процессов в виде неструктурированного набора байт. Со специальным файлом можно работать так же, как и с обычным, то есть открывать, считывать из него определенное количество байт или же записывать в него определенное количество байт, а после завершения операции закрывать. Для этого используются те же системные вызовы, что и для работы с обычными файлами.
Для устройств прямого доступа имеет смысл также указатель текущего положения в файле, которым можно управлять с помощью системного вызова.
Очевидно, что представление устройства в виде файла и использование для управления устройством файловых системных вызовов во многих случаях не позволяет выполнять только достаточно простые операции.