Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
У. Столлингс ГЛАВА 11 Операции в-в и файлы.doc
Скачиваний:
53
Добавлен:
11.05.2015
Размер:
549.89 Кб
Скачать

11.4 Буферизация операций ввода-вывода

Предположим, что пользовательскому процессу необходимо выполнить счи­тывание блоков данных длиной по 512 байт по одному с магнитной ленты. Дан­ные будут считаны в область внутри адресного пространства пользовательского процесса с виртуальным адресом от 1000 до 1511. Наиболее простой путь реше­ния этой задачи — выполнение команды ввода-вывода (что-то наподобие Read_Block [1000, tape]) и ожидание того момента, когда данные станут дос­тупными. Ожидание может быть либо активным, т.е. будет происходить непре­рывное тестирование состояния устройства, либо, что более практично, процесс будет приостановлен до прерывания.

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

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

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

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

Одинарный буфер

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

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

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

Рис. 11.6, Схемы буферизации ввода-вывода (ввод)

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

В книге [KNUT97] приводится грубое, но очень показательное сравнение процессов при использовании одинарной буферизации и при ее отсутствии. Предположим, что Т — это время, необходимое для ввода одного блока, а С — для вычислений, выполняющихся между запросами на ввод данных. Без буфе­ризации общее время выполнения, приходящееся на один блок, будет равно Т + С. При использовании одинарной буферизации время выполнения равно mах[С, Т] + М, где М — время, необходимое для перемещения данных из системного буфера в пользовательскую память. В большинстве случаев это время значительно меньше времени работы без буферизации.

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

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

Двойной буфер

Улучшить схему одинарной буферизации можно путем использования двух системных буферов (рис. 11.6,в). Теперь процесс выполняет передачу данных в один буфер (или считывание из него), в то время как операционная система ос­вобождает (или заполняет) другой. Эта технология известна как двойная буфе­ризация или сменный буфер.

Время выполнения при блочно-ориентированной передаче данных можно грубо оценить как mах[С, Т]. Таким образом, если С < Т , то блочно-ориентированное уст­ройство может работать с максимальной скоростью. Если же С > Т , то двойная бу­феризация избавляет процесс от необходимости ожидания завершения ввода-вывода. В любом случае достигается преимущество перед одинарной буферизацией. Это улучшение буферизации осуществляется за счет увеличения ее сложности.

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

Циклический буфер

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

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

Использование буферизации

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