3.4 ЧТЕНИЕ И ЗАПИСЬ ДИСКОВЫХ БЛОКОВ

3.4 ЧТЕНИЕ И ЗАПИСЬ ДИСКОВЫХ БЛОКОВ

Теперь, когда алгоритм выделения буферов нами уже рассмотрен, будет легче понять процедуру чтения и записи дисковых блоков. Чтобы считать дисковый блок (Рисунок 3.13), процесс использует алгоритм getblk для поиска блока в буферном кеше. Если он там, ядро может возвратить его немедленно без физического считывания блока с диска. Если блок в кеше отсутствует, ядро приказывает дисководу «запланировать» запрос на чтение и приостанавливает работу, ожидая завершения ввода-вывода. Дисковод извещает контроллер диска о том, что он собирается считать информацию, и контроллер тогда передает информацию в буфер. Наконец, дисковый контроллер прерывает работу процессора, сообщая о завершении операции ввода-вывода, и программа обработки прерываний от диска возобновляет выполнение приостановленного процесса; теперь содержимое дискового блока находится в буфере. Модули, запросившие информацию данного блока, получают ее; когда буфер им уже не потребуется, они освободят его для того, чтобы другие процессы получили к нему доступ.

Рисунок 3.12. Состязание за свободный буфер

В главе 5 будет показано, как модули более высокого уровня (такие как подсистема управления файлами) могут предчувствовать потребность во втором дисковом блоке, когда процесс читает информацию из файла последовательно. Эти модули формируют запрос на асинхронное выполнение второй операции ввода-вывода, надеясь на то, что информация уже будет в памяти, когда вдруг возникнет необходимость в ней, и тем самым повышая быстродействие системы. Для этого ядро выполняет алгоритм чтения блока с продвижением breada (Рисунок 3.14). Ядро проверяет, находится ли в кеше первый блок, и если его там нет, приказывает дисководу считать этот блок. Если в буферном кеше отсутствует и второй блок, ядро дает команду дисководу считать асинхронно и его. Затем процесс приостанавливается, ожидая завершения операции ввода-вывода над первым блоком. Когда выполнение процесса возобновляется, он возвращает буфер первому блоку и не обращает внимание на то, когда завершится операция ввода-вывода для второго блока. После завершения этой операции контроллер диска прерывает работу системы; программа обработки прерываний узнает о том, что ввод-вывод выполнялся асинхронно, и освобождает буфер (алгоритм brelse). Если бы она не освободила буфер, буфер остался бы заблокированным и по этой причине недоступным для всех процессов. Невозможно заранее разблокировать буфер, так как операция ввода-вывода, связанная с буфером, активна и, следовательно, содержимое буфера еще не адекватно. Позже, если процесс пожелает считать второй блок, он обнаружит его в буферном кеше, поскольку к тому времени операция ввода-вывода закончится. Если же, в начале выполнения алгоритма breada, первый блок обнаружился в буферном кеше, ядро тут же проверяет, находится там же и второй блок, и продолжает работу по только что описанной схеме.

алгоритм bread /* чтение блока */

входная информация: номер блока в файловой системе

выходная информация: буфер, содержащий данные

{

 получить буфер для блока (алгоритм getblk);

 if (данные в буфере правильные) return буфер;

 приступить к чтению с диска;

 sleep (до завершения операции чтения);

 return (буфер);

}

Рисунок 3.13. Алгоритм чтения дискового блока

Алгоритм записи содержимого буфера в дисковый блок (Рисунок 3.15) похож на алгоритм чтения. Ядро информирует дисковод о том, что есть буфер, содержимое которого должно быть выведено, и дисковод планирует операцию ввода-вывода блока. Если запись производится синхронно, вызывающий процесс приостанавливается, ожидая ее завершения и освобождая буфер в момент возобновления своего выполнения. Если запись производится асинхронно, ядро запускает операцию записи на диск, но не ждет ее завершения. Ядро освободит буфер, когда завершится ввод-вывод.

алгоритм breada /* чтение блока с продвижением */

входная информация:

 (1) в файловой системе номер блока для немедленного считывания

 (2) в файловой системе номер блока для асинхронного считывания

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

{

 if (первый блок отсутствует в кеше) {

  получить буфер для первого блока (алгоритм getblk);

  if (данные в буфере неверные)  приступить к чтению с диска;

 }

 if (второй блок отсутствует в кеше) {

  получить буфер для второго блока (алгоритм getblk);

  if (данные в буфере верные) освободить буфер (алгоритм brelse);

  else приступить к чтению с диска;

 }

 if (первый блок первоначально находился в кеше) {

  считать первый блок (алгоритм bread);

  return буфер;

 }

 sleep (до того момента, когда первый буфер будет содержать верные данные);

 return буфер;

}

Рисунок 3.14. Алгоритм чтения блока с продвижением

Могут возникнуть ситуации, и это будет показано в следующих двух главах, когда ядро не записывает данные немедленно на диск. Если запись «откладывается», ядро соответствующим образом помечает буфер, освобождая его по алгоритму brelse, и продолжает работу без планирования ввода-вывода. Ядро записывает блок на диск перед тем, как другой процесс сможет переназначить буфер другому блоку, как показано в алгоритме getblk (случай 3). Между тем, ядро надеется на то, что процесс получает доступ до того, как буфер будет переписан на диск; если этот процесс впоследствии изменит содержимое буфера, ядро произведет дополнительную операцию по сохранению изменений на диске.

алгоритм bwrite /* запись блока */

входная информация: буфер

выходная информация: отсутствует

{

 приступить к записи на диск;

 if (ввод-вывод синхронный) {

  sleep (до завершения ввода-вывода);

  освободить буфер (алгоритм brelse);

 }

 else if (буфер помечен для отложенной записи)

  пометить буфер для последующего размещения в «голове» списка свободных буферов;

}

Рисунок 3.15. Алгоритм записи дискового блока

Отложенная запись отличается от асинхронной записи. Выполняя асинхронную запись, ядро запускает дисковую операцию немедленно, но не дожидается ее завершения. Что касается отложенной записи, ядро отдаляет момент физической переписи на диск насколько возможно; затем по алгоритму getblk (случай 3) оно помечает буфер как «старый» и записывает блок на диск асинхронно. После этого контроллер диска прерывает работу системы и освобождает буфер, используя алгоритм brelse; буфер помещается в «голову» списка свободных буферов, поскольку он имеет пометку «старый». Благодаря наличию двух выполняющихся асинхронно операций ввода-вывода — чтения блока с продвижением и отложенной записи — ядро может запускать программу brelse из программы обработки прерываний. Следовательно, ядро вынуждено препятствовать возникновению прерываний при выполнении любой процедуры, работающей со списком свободных буферов, поскольку brelse помещает буферы в этот список.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

4.7 ВЫДЕЛЕНИЕ ДИСКОВЫХ БЛОКОВ

Из книги Архитектура операционной системы UNIX автора Бах Морис Дж

4.7 ВЫДЕЛЕНИЕ ДИСКОВЫХ БЛОКОВ Когда процесс записывает данные в файл, ядро должно выделять из файловой системы дисковые блоки под информационные блоки прямой адресации и иногда под блоки косвенной адресации. Суперблок файловой системы содержит массив, используемый для


Чтение и запись

Из книги Справочник по PHP автора

Чтение и запись freadЧитает из открытого файла определенное количество символов.Синтаксис:string fread(int $f, int $numbytes)Читает из файла $f $numbytes символов и возвращает строку этих символов. После чтения указатель файла продвигается к следующему после прочитанного блока позициям. Если


10.5.2. Чтение и запись из процесса

Из книги Разработка приложений в среде Linux. Второе издание автора Джонсон Майкл К.

10.5.2. Чтение и запись из процесса Хотя system() отображает результат работы команды на устройство стандартного вывода и позволяет дочерним программам читать стандартный ввод, это не всегда идеально. Часто процесс желает читать вывод другого процесса либо отправлять текст на


11.2.4. Чтение, запись и перемещение

Из книги VBA для чайников автора Каммингс Стив

11.2.4. Чтение, запись и перемещение Хотя есть несколько способов читать и писать файлы, мы обсудим здесь только простейшие из них[42]. Чтение и запись почти идентичны, поэтому рассмотрим их одновременно.#include <unistd.h>size_t read(int fd, void * buf, size_t length);size_t read(int fd, const void * buf, size_t length);Обе


11.2.5. Частичное чтение и запись

Из книги C++. Сборник рецептов автора Диггинс Кристофер

11.2.5. Частичное чтение и запись Хотя обе функции — и read(), и write() — принимают параметр, указывающий, сколько байт нужно прочитать или записать, ни одна из них не гарантирует, что обработает указанное количество байт, даже если не случается никаких ошибок. Простейший пример


Чтение и запись данных

Из книги Язык программирования Си для персонального компьютера автора Бочков C. О.

Чтение и запись данных Есть несколько VBA-команд для записи и извлечения данных из файла. В приведенной ниже таблице описана их работа. Пример команды Использование Пояснение Оператор Put Предназначен для записи переменных в файл Put #1, 1800, StrQuote (записывает переменную


13.2. Запись и чтение чисел

Из книги Программирование для Linux. Профессиональный подход автора Митчелл Марк

13.2. Запись и чтение чисел ПроблемаТребуется записать число в поток в форматированном виде в соответствии с местными соглашениями.РешениеЗакрепите (imbue) текущую локализацию за потоком, в который вы собираетесь писать данные, и запишите в него числа, как это сделано в


13.3. Запись и чтение дат и времен

Из книги UNIX: разработка сетевых приложений автора Стивенс Уильям Ричард

13.3. Запись и чтение дат и времен ПроблемаТребуется отобразить или прочитать значения дат и времен, используя местные соглашения по форматированию.РешениеИспользуйте тип time_t и tm struct из <ctime>, а также фасеты даты и времени, предусмотренные в <locale>, для записи и чтения


Чтение и запись данных

Из книги QT 4: программирование GUI на С++ автора Бланшет Жасмин

Чтение и запись данных Функции ввода/вывода верхнего уровня позволяют передавать данные различными способами.Операции чтения и записи в потоках начинаются с текущей. позиции в потоке, идентифицируемой как "file pointer"(указатель файла) для потока. Указатель файла изменяется


Чтение и запись данных

Из книги автора

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


18.3. Чтение и запись

Из книги автора

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


19.2. Чтение и запись

Из книги автора

19.2. Чтение и запись Все сообщения в сокете управления ключами должны иметь одинаковые заголовки, соответствующие листингу 19.1[1]. Сообщение может сопровождаться различными расширениями в зависимости от наличия дополнительной информации или необходимости ее