Ю. Вахалия - UNIX изнутри (2003) (1114670), страница 99
Текст из файла (страница 99)
При достижении начала буфер становится наиболее давно использовавшимся и будет предоставлен любому процессу, запросившему свободный буфер. При использовании описанной методики могут возникать некоторые исключительиые ситуации. Первая из иих приводит к повреждению буферов, что происходит в результате огцибок ввода-вывода либо при удалении или обрезании части файла. Такие буферы будут помешеиы в начало очереди цезамедлительио, так как оии гарантированно це будут больше запрошеиы тем же процессом. Вторая проблема имеет место, если «грязиый» буфер успевает достичь начала списка до того, как буфер будет удален из него и переведен в очередь записи дискового драйвера.
После завершения операции записи такой буфер будет помечен как чистый и возвращен в список свободных буферов. Так как очищенный буфер уже достиг начала списка до момента доступа к нему, оц будет возвращен ие в конец списка (как обычно), а в его начало. 9.12.2. Заголовки буфера Каждый буфер представлен своим заголовком. Ядро использует такие заголовки для идентификации и отслеживания буфера, синхронизации доступа к нему, а также для управления кэшем. Заголовок также является интерфейсом к дисковому драйверу. Если необходимо прочесть данные в буфер с диска или осуществить запись, ядро загружает параметры операции ввода-вывода в заголовок и передает этот заголовок дисковому драйверу.
Некоторые важные поля структуры бцГ, представляющей собой заголовок буфера, показаны в табл. 9.2. 420 Глава 9. Реализации файловых систем Таблица 9.2. Поля структуры Ь~Л Описание Поле Статусные флаги гпсЬ йадз мшссьаг "Ь Топе,'Ь ЬасМ Указатели хранения Ьвг в таблице хеширования Указатели хранения Ьиг в очереди свободных буферов зсгссг Ьи1*ач Гога, *ач Ьаск сапог сЬ агЫг меч с Ь ебеч дагкгг сЬ Ыкпс гпс Ь еггог ппггдпед Ь гезгд Указатели на данные Номер устройства Номер блока в устройстве Статус сшибки ввода-вывода Количество оставшихся передаваемых байтов Поле Ь тгадз является битовой маской, задающей несколько флагов.
Ядро использует флаги В ВО5У и В гУАМТЕО для синхронизации доступа к буферу. Флаг В ОЕНЯ1 помечает буфер как «грязныйм Флаги В ВЕАО, В тдй1ТЕ, В А5УВС, В ООМЕ и В ЕВВОВ предназначены для дискового драйвера. Флаг В АОЕ указывает на «старый» буфер, являющийся идеальным кандидатом на повторное использование. 9.12.3. Преимущества 9.12.4. Недостатки Несмотря на очевидные преимущества, буферный кэш не свободен и от некоторых недостатков.
Во-первых, отложенная запись, используемая подсистемой кэширования, может стать причиной потери данных в случае краха ОС. Основной целью использования буферного каша является уменьшение дискового обмена и предупреждение лишних операций ввода-вывода, а также увеличение эффективности работы дисковой подсистемы.
Правильно настроенное кэширование позволяет увеличить производительность примерно на 90% 118~. технология обладает и другими весомыми преимуществами. Буферный кэш синхронизирует доступ к дисковым блокам путем установки флагов 1оскед и вартел. Если два процесса попытаются одновременно запросить один и тот же блок, заблокировать его сможет только один из процессов. Буферный кэш является модульным интерфейсом взаимодействия между дисковым драйвером и другими частями ядра.
Никакая другая подсистема ядра не имеет доступа к драйверу. Интерфейс взаимодействия основан на полях заголовка буфера. Более того, буферный кэш изолирует остальную часть ядра от необходимости приведения ее к требованиям подсистемы ввода-вывода, так как буферы сами по себе организованы постранично. По этому при запросах дискового ввода-вывода по отношению к неупорядоченным адресам у ядра не возникает проблем. 9.12, Буферный кзш в ранних версиях ОНИ 421 При этом целостность дисков может оказаться нарушенной. Более подробно читайте об этой проблеме в разделе 9.12.5. Во-вторых, несмотря на уменьшение общего числа операций доступа к диску, что увеличивает производительность системы, данные приходится копировать дважды: сначала с диска в буфер и только потом в пользовательское адресное пространство.
Второе действие занимает значительно меньше времени, чем первое. Уменьшение общего количества операций за счет кэширования обычно компенсирует затраты на копирование данных из одной области данных в другую, но становится весьма весомым фактором задержки при последовательном чтении или записи в файл большого объема. Такая операция приводит к возникновению ситуации, получившей название «затиранил» кэша (сасЬе ук1р1пя). При необходимости прочтения целиком большого файла, к которому в дальнейшем не потребуется доступ, возникает эффект изменения содержания каша. Так как все блоки файла нужно прочесть за короткий период времени, они постепенно займут все буферы каша, сбрасывая тем самым его предыдущее содержимое. Это приводит к некоторому временному промежутку неэффективности каша до тех пор, пока он снова не заполнится более полезными данными, что уменьшает производительность системы.
Защититься от проблемы затирания каша можно на прикладном уровне. Например, в файловой системе адептах (ЧхГЯ) позволяется пользователю указать, каким именно образом следует производить доступ к файлам. При помощи этого средства можно запретить кэширование больших файлов и запросить систему передавать данные с диска напрямую в пользовательское адресное пространство, минуя промежуточный буфер. 9.12.5.
Целостность файловой системы Основной проблемой, связанной с применением кэша, является несовпадение данных на диске с их текущим состоянием. Если система работает нормально, это не является критичным, так как ядро использует блоки, содержащие «свежие» копии дисковых данных. Проблема возникает в случае краха системы, при котором могут быть потеряны внесенные изменения. Такими данными могут оказаться как блоки файлов, так и их метаданные. В системах ()1х! Х принято обрабатывать потерю этих двух типов информации по-разному. С точки зрения операционной системы потеря данных при записи на диск является не столь катастрофичной, как для пользователя, поскольку при этом не нарушается целостность файловой системы. Если производить все операции записи на диск синхронно, снижение производительности системы станет значительным, поэтому по умолчанию используется технология отложенной записи.
Существуют несколько способов, заставляющих ядро системы сбросить данные на диск. Системный вызов эупс выполняет запись на диск содержимого всех «грязных» буферов. При этом, однако, ядро не ждет завершения процедуры записи, поэтому не существует гарантии того, что конкретный блок будет являться актуальным после завершения работы эупс, 422 Глава 9. Реализации файловых систем Пользователь также может открывать файл в синхронном режиме, после чего все операции записи в этот файл будут производиться синхронно. Некоторые реализации системы используют демон обновления (в БЪ'24 это процесс под названием Гз11цзл), который периодически (по умолчанию каждые 30 секунд) вызывает зупс для очистки кэша.
При потере метаданных файловая система теряет свою целостность. Изменения в метаданных производят многие файловые операции; если при этом какие-либо из модификаций не будут сохранены на диск при крахе ОС, файловая система может оказаться поврежденной. Например, при добавлении ссылки к файлу происходит запись элемента нового имени в соответствующий каталог и увеличение счетчика ссылок в индексном дескрипторе.
Представьте, что крах системы произошел как раз в тот момент, когда были записаны изменения в каталоге, но внесенные в индексный дескриптор данные не сохранены на диск. После перезагрузки системы мы увидим два элемента каталогов, указывающих на файл, имеющий всего одну ссылку. Если этот файл будет удален, то его индексный дескриптор и занимаемые блоки будут освобождены, так как значение счетчика ссылок уменьшилось теперь до значения «ноль». Второе вхождение будет указывать на незанятый (или указывающий уже на другой файл) индексный дескриптор. Возникновение подобных ситуаций в системе необходимо уметь предупреждать. Существуют две методики защиты от повреждения файловой системы, применяемые в БМ1Х. Ядро выбирает определенный порядок записи метаданных, уменьшающий влияние крахов системы.
Представьте, что получится, если в предыдущем примере поменять порядок операций записи: после краха системы дескриптор стал уже обновленным, но не произошла запись в каталог. После перезагрузки такой файл будет иметь дополнительную ссылку, но при этом оригинальное вхождение каталога окажется правильным и доступ к файлу может быть продолжен без каких-либо проблем. Если файл будет удален, пропадет элемент каталога, но не освободятся блоки и индексный дескриптор, так как на этот файл останется еще одна ссылка. Такой подход, конечно, не защищает от повреждений, но проводит к меньшей степени вреда, чем в исходном примере.
Порядок записи метаданных должен определяться очень внимательно. Проблема порядка выполнения остается по-прежнему, потому что дисковый драйвер обслуживает запросы не в порядке их получения. Чтобы указать порядок выполнения запросов, у ядра есть единственное средство — сделать операции синхронными. Следовательно, в описанном примере ядро произведет запись индексного дескриптора на диск, подождет завершения этой операции и затем вызовет запись в каталог. Ядро использует синхронную запись метаданных во многих операциях, требующих изменения нескольких взаимосвязанных объектов [2]. Вторым методом борьбы с повреждением файловой системы является применение утилиты 1зсМ [4], [10]. Эта программа проводит диагностику файло- 9.14. Упражнения 423 вой системы, находит нарушения целостности и восстанавливает ее, если это возможно.
Если метод исправления не очевиден, программа попросит пользователя выбрать наиболее приемлемый. По умолчанию системный администратор выполняет Ьск каждый раз при перезагрузке системы. Программа также может быть запущена в любой момент времени по требованию, Утилита Ься использует прямой доступ к дисковому драйверу для доступа к файловой системе (см. более подробно в разделе 11.2.4).