Скачиваний:
71
Добавлен:
02.05.2014
Размер:
253.95 Кб
Скачать

6.7. Буферизация

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

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

Богатые вариантами средства организации ввода-вывода с использованием буферизации были впервые реализованы в OS/360 [21] и унаследованы следующими поколениями ОС мейнфреймов. При синхронной организации ввода-вывода (в OS/360 – "методы доступа с очередями") буферизация прозрачна для процесса, она полностью обеспечивается ОС. При асинхронной организации ("базисные методы доступа") процесс сам может организовать буферизацию. Устройству назначается буферная область, которая форматируется как буферный пул. В методах с очередями это назначение происходит автоматически, программист может только изменить размер пула, если его не устраивает принятый по умолчанию. В базисных методах есть специальные системные вызовы для выделения, освобождения, форматирования буферного пула и связывания пула с устройством. Буферизация не обязательно означает дополнительную пересылку данных в оперативной памяти. Методы с очередями предоставляют три альтернативных режима управления буферизацией:

  • режим пересылки – данные пересылаются в оперативной памяти между рабочей областью процесса и буфером;

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

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

Два интересных примера буферизации мы возьмем из ОС Unix.

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

  • состояние буфера (свободен / содержит правильную информацию / грязный / заблокирован / занят в операции ввода/вывода/ожидается каким-либо процессом);

  • адрес на внешней памяти блока информации, содержащегося в буфере;

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

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

  • если буфера нет в хеш-очереди и список свободных блоков пуст;

  • если буфер есть в хеш-очереди, но занят.

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

Все современные ОС (OS/2, Windows 95, Windows NT) в той или иной степени применяют тотальное кеширование при обмене с дисками.

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

  • указатель на следующий блок в цепочке;

  • смещение первого символа в поле данных;

  • смещение последнего символа в поле данных;

  • поле данных для хранения N символов.

Пример буфера при N=8 показан на рисунке 6.7. Ядро ОС хранит указатели на первый и последний блоки цепочки и ведет список свободных блоков (очередь LIFO). Ядро обеспечивает:

  • назначение драйверу свободного блока;

  • возвращение блока в список свободных;

  • выбор первого символа из буфера (при этом возможно освобождение блока);

  • добавление символа в конец буфера (при этом возможно выделение нового блока).

Рисунок 6.7 Буфер терминала для Unix

Соседние файлы в папке Системное программирование и операционные системы