Как показано на Рисунке 2.1, алгоритмы верхнего уровня, используемые ядром для подсистемы управления файлами, инициируют выполнение алгоритмов управления буферным кешем. При выборке блока алгоритмы верхнего уровня устанавливают логический номер устройства и номер блока, к которым они хотели бы получить доступ. Например, если процесс хочет считать данные из файла, ядро устанавливает, в какой файловой системе находится файл и в каком блоке файловой системы содержатся данные, о чем подробнее мы узнаем из . Собираясь считать данные из определенного дискового блока, ядро проверяет, находится ли блок в буферном пуле, и если нет, назначает для него свободный буфер. Собираясь записать данные в определенный дисковый блок, ядро проверяет, находится ли блок в буферном пуле, и если нет, назначает для этого блока свободный буфер. Для выделения буферов из пула в алгоритмах чтения и записи дисковых блоков используется операция getblk (Рисунок 3.4).
Рассмотрим в этом разделе пять возможных механизмов использования getblk для выделения буфера под дисковый блок.
Обсудим каждый случай более подробно.
Осуществляя поиск блока в буферном пуле по комбинации номеров устройства и блока, ядро ищет хеш-очередь, которая бы содержала этот блок. Просматривая хеш-очередь, ядро придерживается списка с указателями, пока (как в первом случае) не найдет буфер с искомыми номерами устройства и блока. Ядро проверяет занятость блока и в том случае, если он свободен, помечает буфер "занятым" для того, чтобы другие процессы не смогли к нему обратиться. Затем ядро удаляет буфер из списка свободных буферов, поскольку буфер не может одновременно быть занятым и находиться в указанном списке. Если другие процессы попытаются обратиться к блоку в то время, когда его буфер занят, они приостановятся до тех пор, пока буфер не освободится. На Рисунке 3.5 показан первый случай, когда ядро ищет блок 4 в хеш-очереди, помеченной как "блок 0 модуль 4". Обнаружив буфер, ядро удаляет его из списка свободных буферов, делая блоки 5 и 28 соседями в списке.
алгоритм getblk входная информация: номер файловой системы номер блока выходная информация: буфер, который можно использовать для блока { выполнить если (буфер не найден) { если (блок в хеш-очереди) { если (буфер занят) /* случай 5 */ { приостановиться (до освобождения буфера); продолжить; /* цикл с условием продолжения */ } пометить буфер занятым; /* случай 1 */ удалить буфер из списка свободных буферов; вернуть буфер; } в противном случае /* блока нет в хеш-очереди */ { если (в списке нет свободных буферов) /*случай 4*/ { приостановиться (до освобождения любого буфера); продолжить; /* цикл с условием продолжения */ } удалить буфер из списка свободных буферов; если (буфер помечен для отложенной переписи) /* случай 3 */ { асинхронная перепись содержимого буфера на диск; продолжить; /* цикл с условием продолжения */ } /* случай 2 -- поиск свободного буфера */ удалить буфер из старой хеш-очереди; включить буфер в новую хеш-очередь; вернуть буфер; } } } |