Иллюстрированный самоучитель по Computer Network The Hands

         

Драйверы файловых систем


Драйверы файловых систем

При эксплуатации ОС может возникнуть необходимость монтировать файловые системы, отличающиеся от "родной" ФС. Особенно часто она возникает в организациях, где используются ОС нескольких разных типов. Да и в организациях, работающих с монокультурой MS DOS/MS Windows, такая потребность возникает все чаще. Во-первых, доступ к файлам на файловом сервере осуществляется существенно иными способами, чем к файлам локальном диске, даже если на сервере стоит та же ДОС с той же Фс тип FAT. Во-вторых, дисководы для CD-ROM становятся все дешевле и расгт страняются все шире. При этом стандартная ФС на CD-ROM — вовсе FAT.

Решение этой проблемы приходит в голову сразу — необходим драйвеп файловой системы со стандартным интерфейсом, подобный драйверу ннеш него устройства. Естественно, набор функций такого драйвера должен быть существенно иным.

mount — монтирование ФС. В зависимости от типа ФС параметры тгой функции должны различаться. Для ФС на локальных дисках достаточно передать системный идентификатор монтируемого диска. Для ФС на удаленной машине мы должны передать сетевой адрес этой машины и имя требуемой файловой системы. Во многих случаях проводится различие между монтированием ФС для чтения/модификации или только для чтения: при монтировании с модификацией устанавливается флаг загрязнения (dirty flag) ФС.

umount — размонтирование ФС.

GetFreeSpace или df — получение информации о ФС: общее пространство, свободное пространство, количество файлов и т. д.

FindFirst/FindNext ИЛИ opendir/readdir — функции длячтения из каталога. Считанную информацию необходимо привести к формату, принятому в данной ОС. В частности, может оказаться необходимым сократить и/или преобразовать считанные имена файлов. Например, драйвер HPFS, используемый в-эмуляторе MS DOS, в системе OS/2 не выполняет такого преобразования. В результате — программы DOS не видят файлов и каталогов с длинными именами.

access — проверить существование файла и возможность доступа к нему в заданном режиме, например, для чтения или для записи.

stat — функция для получения информации о файле с заданным именем. Драйвер ФС должен считать доступную информацию о файле и привести ее к принятому в ОС формату. При этом возможно придется проигнорировать часть считанной информации, а другую часть, напро-- тив, драйвер вынужден сочинять сам. Так, драйвер файловой системы FAT в ОС семейства Unix вынужден сочинять идентификатор хозяина файла, права доступа и т. д.

open - открыть существующий или создать новый файл с заданным именем.

read и write — функции считывания данных из файла ц записи в него.

lseek — позиционирование в файле.

lock — функция (в действительности, набор функций) блокировки для

синхронизации доступа к файлу или его участкам. (Подробнее о них см. в

разд. Захват участков файлов). При работе с локальными ФС операции блокировки могут прослеживаться ядром системы и не доходить до драйвера ФС, но при

работе с разделяемыми по сети ФС блокировки необходимо отслеживать

на уровне протокола разделения файлов, поэтому драйвер сетевой ФС

обязан знать о блокировках.

close — закрыть файл.



delete или unlink — удалить файл или его имя.

link — создать связь с файлом (новое имя). Далеко не все ОС и ФС поддерживают эту операцию.

mkdir — создать каталог.

rmdir — удалить каталог. Обычно разрешено удаление только пустых каталогов.

Кроме собственно драйвера ФС, для ее полноценной поддержки нужны следующие программы:

программа создания ФС — mkfs или FORMAT;

программа контроля и починки ФС — fsck или CHKDSK;

программа fstyp, которая смотрит на содержимое устройства и пытается определить, "ее" это ФС или не ее. Она полезна при монтировании ФС с автоматическим определением ее типа;

программа mount, которая принимает из командной строки зависящие от типа ФС параметры, проверяет их допустимость и инициализирует драйвер ФС.

Драйверы файловых систем в SCO UnixWare

Например, дистрибутив ОС UnxiWare 2.0 фирмы SCO, основанной на ядре UNIX System V R4.2, содержит драйверы следующих файловых систем.

memfs — файловая система, размещающая файлы в оперативной памяти. Может рассматриваться как эквивалент виртуального диска в MS DOS.

dosfs — файловая система FAT.

s5 — "классическая" ФС, сохранившаяся почти без изменений с самых ранних версий системы— s5, по-видимому, означает Unix System 5. Ограничивает имя файла 14 символами. Неустойчива к сбоям.

ufs — файловая система, разработанная в университете Беркли, известная также как FFS (Fast File System) и Berkley FS. Является основной ФС в большинстве версий BSD UNIX и поддерживается многими другими ОС семейства Unix. Имеет более высокую производительность, чем s5, в первую очередь за счет разбиения таблицы инодов и списка свободных блоков на участки (группы цилиндров). Поддерживает дисковые квоты ограничения на объем дискового пространства, занятого файлами того и~~ иного пользователя. Ограничивает имя файла размером блока (обычно 512 символов). Неустойчива к сбоям.

bfs — Boot File System — загрузочная файловая система. Эта ФС очень простую структуру, отчасти похожую на файловую систему

все файлы в ней обязаны занимать непрерывное пространство. "Гака структура упрощает первичный загрузчик системы, которому теперь не нужно разбираться в каталогах и инодах. bfs имеет довольно низкую про-изводительность и требует длительной процедуры размонтирования. если в нее были записаны новые данные. Фактически, при таком размонтирова-нии происходит операция сжатия ФС, эквивалентная команде SQEESE в RT-11. Используется для хранения ядра системы и нескольких конфигурационных файлов, применяемых при загрузке. Все эти данные считываются лишь при загрузке системы и перезаписываются только при изменениях конфигурации ядра, поэтому высокая производительность от этой ФС не требуется.

vxfs — устойчивая к сбоям ФС Veritas с регистрацией намерений. Версия, входящая в стандартную поставку системы, включает в регистрируемые транзакции только системные структуры данных. За отдельную плату можно приобрести "продвинутую" версию Veritas, которая обеспечивает транзакции и для записи пользовательских данных.

cdfs — файловая система ISO, используемая на CD-ROM.

nfs — Network File System — драйвер файловой системы, обеспечивающий разделение файлов с использованием сетевого протокола TCP/IP. Протокол NFS был предложен фирмой Sun Microsystems в середине 80-х годов и в настоящее время поддерживается практически всеми членами семейства Unix. NFS-клиенты и NFS-серверы реализованы практически для всех современных ОС.

rfs — Remote File Sharing — использование удаленной UNIX-системы в качестве файлового сервера. Этот протокол был разработан фирмой AT&T в 80-е годы и пригоден только для соединения систем UNIX System V.

nucfs — NetWare Unix Client File System. Этот драйвер предназначен для присоединения к файловым серверам Novell Netware. Он входит в состав системы UnixWare, поставляемой фирмой SCO, но не в остальные версии UNIX SVR4.

Любопытно, что даже MS/DR DOS версий выше 3.30 имеют возможность устанавливать драйвер файловой системы. Такой драйвер может быть реализован путем перехвата недокументированных функций прерывания 0x2F — группы функций "Network Redirector" и "IPS". Таким образом реализован ряд сетевых клиентов для MS/DR DOS. К сожалению, автор не смог найти полноценного описания этих функций.



Файловые системы


Файловые системы

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

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

Понятие файла вводится в самом начале любого курса компьютерного ликбеза, но мало в каком курсе дается внятное определение этого понятия. Слово файл (file) дословно переводится с английского как папка или подшивка, но такой перевод почти не добавляет ясности. Одно из наилучших определений, известных автору, звучит так: "Файл — это совокупность данных, доступ к которой осуществляется по ее имени".

файл, таким образом, противопоставляется другим объектам, доступ к которым осуществляется по их адресу, например, записям внутри файла или блокам на диске.

Примечание

ОС семейства Unix трактуют понятие файла более широко — там файлом называется любой объект, имеющий имя в файловой системе. Однако файлы, не являющиеся совокупностями данных (каталоги, внешние устройства, псевдоустройства, именованные программные каналы, семафоры Xenix), часто называют не простыми файлами, а "специальными".

Из разд. Запоминающие устройства прямого доступа нам известно, что магнитный диск или другое устройство памяти (кроме, пожалуй, файлового сервера) чаще всего организует доступ к данным не по их именам, а все-таки по адресам, например, по номеру сектора, дорожки и поверхности диска. Поэтому, если система хочет предоставлять доступ по именам, она должна хранить таблицу преобразования имен в адреса — директорию (directory), или, как чаще говорят по-русски, каталог. В каталоге хранится имя файла и другая информация о файле, такая, как его размер и местоположение на диске. Как правило, хранят также дату создания файла, дату его последней модификации, а в многопользовательских системах — идентификатор хозяина этого файла и права доступа к нему для других пользователей. Во многих файловых системах эта информация хранится не в самом каталоге, а в специальной структуре данных иноде, метафайле и т. д. В этом случае запись в каталоге содержит только имя и указатель на управляющую структуру файла.

Большинство современных операционных систем позволяет делать вложенные каталоги — файлы, которые сами являются каталогами. В таких системах файл задается полным или путевым именем (path name), состоящим из цепочки имен вложенных каталогов и имени файла в последней из них.

Совокупность каталогов и системных структур данных, отслеживающих размещение файлов на диске и свободное дисковое пространство, называется файловой системой (ФС). Иногда на диске размещается только одна файловая система. Современные ОС часто позволяют размещать на одном физическом диске несколько файловых систем, выделяя каждой из них фиксированную часть диска. Такие части диска называются разделами (partition) или слайсами (slice). Обычно разбиение диска на части производится на уровне драйвера диска, поэтому общее название частей — логические диски. С другой стороны, ряд файловых систем может занимать несколько дисков.



Файловые системы с регистрацией намерений


Файловые системы с регистрацией намерений

Термин, вынесенный в заголовок этого подраздела, является дословной калькой (возможно, не очень удачной) англоязычного термина intention logging. В русском языке, к сожалению, еще нет общепринятого термина для этого понятия.

Идея журналов регистрации намерений пришла из систем управления базами данных. В СУБД часто возникает задача внесения согласованных изменений в несколько разных структур данных. Например, банковская система переводит миллион долларов с одного счета на другой. СУБД вычитает 1 000 000 из суммы на первом счету, затем пытается добавить ту же величину ко второму счету и в этот момент происходит сбой.

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

Удовлетворительное решение проблемы заключается в следующем.

Во-первых, все согласованные изменения в СУБД организуются в блоки, называемые транзакциями (transaction). Каждая транзакция осуществляется как неделимая (атомарная) операция, во время которой никакие другие операции над изменяемыми данными не разрешены.

Во-вторых, каждая транзакция осуществляется в три этапа (рис. 11.21)

Система записывает в специальный журнальный файл, что же она с бирается делать.

Если запись в журнал была успешной, система выполняет транзакцию.

Если транзакция завершилась нормально, система помечает в журнале, что намерение было успешно реализовано.


Рис. 11.21. Выполнение транзакции с регистрацией намерений

Журнал часто называют журналом регистрации намерений (intention log), что очень хорошо отражает суть дела, потому что в этот журнал записываются именно намерения (intentions).

При использовании отложенной записи транзакция считается полностью завершенной, только когда последний блок измененных данных будет физически записан на диск. При этом в системе обычно будет одновременно существовать несколько незавершенных транзакций (рис. II.22). Легко понять, что при операциях с самим журналом отложенную запись вообше нельзя использовать.

Рис. 11.22. Очередь исполняющихся транзакций

Если произошел сбой системы, после перезагрузки запускается программа восстановления базы данных (рис. 11.23). Эта программа просматривает конец журнала.

Если она видит там испорченную запись, то игнорирует ее: сбой произошел во время записи в журнал.

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

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

Нужно отметить, что данные, необходимые для выполнения отката, могут иметь большой объем. Фактически это копия всех данных, подвергающихся Изменению в ходе транзакции. Многие СУБД, такие как ORACLE, хранят эти данные не в самом журнале, а в специальной области данных, называемой сегмент отката (rollback segment).

Рис. 11.23. Журнал транзакций после сбоя

Более подробная информация о работе журналов намерений в базах данных может быть найдена в соответствующей литературе [Дейт 1999, Дейт 1988). Необходимо только отметить, что книги и даже фирменная документация по простым СУБД типа dBase или FoxPro здесь не помогут, поскольку эти пакеты не содержат средств регистрации в журнале.

Идея журнала намерений достаточно естественно переносится в программу управления файловой системой. Но здесь возникает интересный вопрос -что же считать транзакцией: только операции по распределению пространства на диске или также все операции по изменению данных?

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

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

ряд современных ФС с регистрацией намерений поддерживают оба режима работы и предоставляют выбор между этими вариантами администратору системы. Например, у файловой системы vxfs пли Veritas, входящей в пакет UnixWare (версия Unix SVR4, поставляемая фирмой Novell), существует две версии. Одна версия, поставляемая вместе с системой по умолчанию, включает в транзакцию только системные данные. Другая, "advanced", версия, которая поставляется за отдельные деньги, осуществляет регистрацию намерений как для системных, так и для пользовательских данных.

Журналы намерений в Veritas

В Veritas 2 дисковый том разбит на области, называемые группами цилиндров (термин, унаследованный из FFS— файловой системы BSD Unix). Каждая группа цилиндров имеет свою карту свободных блоков, участок динамической таблицы инодов и журнал намерений (рис. 11.24). Журнал намерений организован в виде кольцевого буфера записей о транзакциях. В журнал пишутся данные только о транзакциях над инодами, принадлежащими к этой группе цилиндров. При этом в каждой группе может исполняться одновременно несколько транзакций и окончанием транзакции считается физическое завершение записи модифицированных данных. Количество одновременно исполняющихся транзакций ограничено объемом журнала, но поскольку каждая группа цилиндров имеет свой журнал, это ограничение не играет большой роли.

Рис. 11.24. Группы цилиндров и журналы транзакций Veritas



Файлы с точки зрения пользователя


Файлы с точки зрения пользователя

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

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



Формат имен файлов


Формат имен файлов

В различных ФС допустимое имя файла может иметь различную длину ц нем могут использоваться различные наборы символов. Так, в RT-H и RSX-Ц имена файлов состоят из символов кодировки RADIX-50 и имеют длину 9 символов: 6 символов — собственно имя, а 3 — расширение. При этом имя имеет вид "ХХХХХХ.ХХХ", но символ '.' не является частью имени — это просто знак препинания. Предполагается, что расширение должно соответствовать типу данных, хранящихся в файле: SAV будет именем абсолютного загружаемого модуля, FOR — программы на Фортране, CRH - "файлом информации о системном крахе", как было написано в одном переволе руководства (попросту говоря, это посмертная выдача ОС, по которой можно попытаться понять причину аварии).

В СР/М и ее потомках MS DOS-DR DOS, а также в VMS имена файлов хранятся в 8-битной ASCII-кодировке, но почему-то разрешено использование только букв верхнего регистра, цифр и некоторых печатаемых символов. При этом в системах линии СР/М имя файла имеет 8 символов плюс 3 символа расширения, а в VMS как имя, так и расширение могут содержать более 32 символов. Все перечисленные системы используют нечувствительный к регистру букв поиск в каталогах: имена file.с, File.С и FILE.С считаются одним и тем же именем.

Ограничения на формат имени в MS DOS

Любопытно, что MS/DR DOS при поиске в каталоге переводят в верхний регистр имя, заданное пользователем, но оставляют без изменений имя, считанное из каталога. Строго говоря, это ошибка: если мы создадим имя файла, содержащее буквы нижнего регистра, то ни одна программа не сможет открыть или переименовать такой файл.

Автору довелось столкнуться с такой проблемой при попытке прочитать дискету, записанную ОС ТС (Экспериментальная UNIX-подобная ОС для Паскаль-машины N9000). Проблему удалось решить только при помощи шестнадца-теричного дискового редактора прямым редактированием имен в каталогах. Возможно, существует и более элегантное решение, но автору не удалось его найти.

Использовать конструкцию *.* бесполезно, потому что, в действительности, операции над файлами, заданными таким образом, состоят из двух операций: FindFirst/FindNext, которая возвращает [следующее] имя файла, соответствующее шаблону, и Open. FindFirst/FindNext возвращает недопустимое имя файла и Open не может использовать его. Программа CHKDSK не возражает против имен файлов в нижнем регистре. Строго говоря, это тоже ошибка. Все остальные способы, так или иначе, сводятся к прямой (в обход ДОС) модификации ФС.

Кроме того, любопытных эффектов можно достичь, попытавшись создать файл с именем, содержащим русские буквы.

Наибольшим либерализмом в смысле имен отличаются ОС семейства Unix, в которых имя файла может состоять из любых символов кодировки ASCII, кроме символов '\000' и V, например, из восьми символов перевода каретки. При этом '\000' является ограничителем имени, а V — разделителем между именем каталога и именем файла. Никакого разделения на имя и расширение нет, и хотя имена файлов с программой на языке С заканчиваются ".с", а объектных модулей — ".о", точка здесь является частью имени. Вы можете создать файл с именем "gcc-2.5.8.tar.gz". В UNIX SVR3 длина имени файла ограничена 14 символами, а в BSD UNIX, Linux и SVR4— только длиной блока на диске, т. е. 512 байтами или более. При этом нулевой символ считается концом имени в каталоге.

Возможность использовать в именах неалфавитные символы типа перевода каретки или ASCII EOT (End Of Transmission) кажется опасным излишеством. На самом деле:

это не излишество а, скорее, упрощение — из процедур, работающих с именами, удалена проверка символа на "допустимость";

оно не столь уж опасно: такой файл всегда можно переименовать.

В некоторых случаях процесс набора имени файла в командной строке превращается в нетривиальное упражнение, потому что shell (командный процессор) рассматривает многие неалфавитные символы как команды. Но надо отметить, что, правильно используя кавычки и символ '\', пользователь может передать команде аргумент, содержащий любые символы ASCII, кроме \000".

Длинные имена файлов в ОС семейства СР/М

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

Например, OS/2, использующая файловую систему HPFS (High Performance File System — высокопроизводительная файловая система), поддерживает имена файлов длиной до 256 символов, содержащие печатаемые символы и пробелы. Точка считается частью имени, как и в UNIX, и можно создавать имена, содержащие несколько точек. Аналогичную структуру имеют имена в NTFS, используемой в Windows NT/2000/XP, VFAT (реализация файловой системы FAT16, используемая в Windows 95/98/ME) и FAT32.

Описанные ОС при поиске файла приводят к одному регистру все алфавитные символы в имени. С одной стороны, это означает дополнительное Удобство для пользователя — при наборе имени не нужно заботиться о регистре букв, с другой — пользователь не может создать в одном каталоге файлы "text.txt" и "Text.txt". Из-за этого, например, нельзя использовать принятое в UNIX соглашение о том, что файл на языке С имеет расширение "с", а на языке C++ — "С".

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

Некоторые ОС, например, RSX-11 и VMS, поддерживают также номер версии файла. В каталоге может существовать несколько версий файла с одним именем; если номер версии при открытии файла не задается, то открывается последняя версия.

Версии файла очень удобны при разработке любых объектов, от программ или печатных плат до книг: если вам не понравились изменения, внесенные вами в последнюю версию, вы всегда можете откатиться назад. Ныне функцию хранения предыдущих версий изменяемых файлов и управляемого отката к ним реализуют специальные приложения, системы управления версиями (version control system) (RCS, CVS и др.).



Монтирование файловых систем


Монтирование файловых систем

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

Проверку типа монтируемой ФС.

Проверку целостности ФС.

Считывание системных структур данных и инициализацию соответствующего модуля файлового менеджера (драйвера файловой системы).

В некоторых случаях — модификацию ФС с тем, чтобы указать, что она уже смонтирована. При этом устанавливается так называемый флаг загрязнения (dirty flag). Смысл этой операции будет объяснен и разд. Устойчивость ФС к сбоям.

Включение новой файловой системы в общее пространство имен (рис. 11.1). В различных системах это делается различными способами.

Многие пользователи MS/DR DOS никогда не сталкивались с понятием монтирования. Дело в том, что эта система (как и многие другие ДОС, например RT-11) выполняет упрощенную процедуру монтирования при каждом обращении к файлу. Упрощения состоят в пропуске шагов 1 и 2 и отсутствии шага 4 (ФС MS/DR DOS устойчива к сбоям).

ДОС, как правило, помещают в пространство имен все доступные блочные устройства, не выполняя полной процедуры монтирования. Если какое-то из этих устройств не содержит ФС известного типа, то система будет возмущаться при обращениях к такому устройству, но не удалит его из списка доступных ФС. А иногда даже не будет возмущаться — попробуйте поставить в дисковод машины под управлением MS/DR DOS-дискету, не содержащую файловой системы (например, созданную программой tar) и в командной строке набрать DIR А:. Скорее всего, вы увидите несколько экранов мусора, но ни одного сообщения об ошибке!

Рис. 11.1. Пространство имен ОС с несколькими ФС

Если мы монтируем ФС, размещенную на удаленной машине (файловом сервере), то шаги 1 и 2 заменяются на установление соединения этим сервером. В системах семейства СР/М при работе с файловыми серверами Novell Netware монтирование серверных файловых систем производится командой MAP, а с файловыми серверами, поддерживающими протокол SMB, — командой NET USE.

Обычно имя файла в подмонтированной файловой системе имеет вид 'ИМЯ_ФС:\имена\каталогов\имя.файла'. При этом вместо разделителей ':' и '/' могут использоваться другие символы.

Имена файловых систем в RT-11, RSX-11, VMS

В RT-11, RSX-11 и VMS в качестве имени файловой системы используется имя физического устройства, на котором размещена ФС. Если применяется DECNet, перед именем устройства можно поместить имя узла сети, на котором это устройство находится. Полное имя файла в VMS выглядит так: DUAO-lUSERS.FAT_BROTHER.WORKJtest.exe. При этом DUAO означает дисковое устройство 0, присоединенное к дисковому контроллеру A: Disk Unit д [device #] О, [USERS.FAT_BROTHER.WORK] означает каталог WORK в каталп FAT_BROTHER в каталоге USERS.

Имена файловых систем в ОС семейства СР/М

В системах семейств СР/М имена файловых систем обозначаются буквами ла тинского алфавита, а сами файловые системы часто почему-то называются "драйвами". При некотором желании можно использовать в качестве имен фг также символы '[' и ']'. Устройства А: и В: — это всегда приводы гибких дисков устройство С: — обычно первый жесткий диск, или первый раздел на первом жестком диске.

Автора всегда интересовал вопрос: "Что будет делать пользователь, когда у него кончатся доступные буквы алфавита?" При использовании только локальных дисков такая ситуация кажется маловероятной, но при подключении к нескольким файловым серверам количество используемых файловых систем резко возрастает...

В OS/2 и Windows for Workgroups эта проблема решена использованием так называемых UNC-имен, задающих имя файла в виде \\NODE\SHARE\ PATH\FILE.NAM (рис. 11.2), где NODE — имя сетевого узла, SHARE — имя разделяемого ресурса на этом узле (это может быть не только разделяемый каталог, но и принтер, а в OS/2 также и модем), a PATH\FILE.NAM — путь к файлу относительно разделяемого каталога. К сожалению, далеко не все старые (и даже многие не очень уж старые) программы понимают такие имена. Например, даже стандартный командный процессор системы Windows NT не может исполнить команду cd \\NODE\SHARE\DIR (проверялось на NT 4.0 sp4-6, 2000 sp 1 и ХР).

Рис. 11.2. UNC-имена

Структура пространства имен в Unix

В операционных системах семейства Unix смонтированные ФС выглядят как каталоги единого дерева (строго говоря, структура каталогов в UNIX не обязана являться деревом; но об этом см. разд. Cложные файловые системы), Это дерево начинается с корневого каталога, выделенной ФС, называемой корневой (root). Администратор системы может подмонтировать новую ФС к любому каталогу, находящемуся на любом уровне дерева (рис. 11.3). Такой каталог после этого называют точкой монтирования, но это выражение отражает только текущее состояние каталога. После того как мы размонтируем ФС, мы сможем использовать этот каталог как обычный, и наоборот, мы можем сделать точкой монтировки любой каталог.

Рис. 11.3. Структура пространства имен в Unix

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

По традиции все Unix-системы имеют примерно одинаковую структуру дерева каталогов: системные утилиты находятся в каталоге /bin, системные библиотеки — в каталоге /lib, конфигурационные файлы — в каталоге /etc и т. д. Например, база данных об именах пользователей всегда находится в файле /etc/passwd.

Точки монтирования реализованы и в некоторых ОС, не относящихся к семейству Unix. Так, свободно распространяемый продукт TVFS (Toronto Virtual File System) для OS/2 позволяет объединять несколько различных файловых систем (как локальных, так и сетевых) в один логический диск, монтируя реальные ФС в каталоги виртуальной. Аналогичная функциональность была реализована в Windows 2000, но почему-то только в поставке Advanced Server.



Операции над файлами


Операции над файлами

Большинство современных ОС рассматривают файл как неструктурированную последовательность байтов переменной длины. В стандарте POSIX над файлом определены следующие операции.

int open(char * fname, int flags, mode_t mode)

Эта операция "открывает" файл, устанавливая соединение между программой и файлом. При этом программа получает "ручку" или дескриптор файла — целое число, идентифицирующее данное соединение. Фактически это индекс в системной таблице открытых файлов для данной задачи. Все остальные операции используют этот индекс для ссылки на файл. Параметр char * fname задает имя файла, int flags — это битовая маска, определяющая режим открытия файла. Файл может быть открыт только для чтения, только для записи и для чтения и записи; кроме того, можно открывать существующий файл, а можно пытаться создать новым файл нулевой длины. Необязательный третий параметр mode используется только при создании файла и задает атрибуты этого файла.

off_t lseek(int handle, off_t offset., int whence)

Эта операция перемещает указатель чтения/записи в файле. Параметр offset задает количество байтов, на которое нужно сместить указатель, а параметр whence — начало отсчета смещения. Предполагается, что смещение можно отсчитывать от начала файла (SEEK_SET), от его кониа (SEEK_END) и от текущего положения указателя (SEEK_CUR). Операция возвращает положение указателя, отсчитываемое от начала файла. Таким образом, вызов iseek (handle, о, SEEK_cuR) возвратит текущее положение указателя, не передвигая его.

int read(int handle, char * where, size__t howjnuch)

Операция чтения из файла. Указатель where задает буфер, куда нужно поместить прочитанные данные; третий параметр указывает, сколько данных надо считать. Система считывает требуемое число байтов из файла, начиная с указателя чтения/записи в этом файле, и перемещает указатель к концу считанной последовательности. Если файл кончился раньше, считывается столько данных, сколько оставалось до его конца. Операция возвращает количество считанных байтов. Если файл открывался только для записи, вызов read возвратит ошибку.

int write(int handle, char * what, size__t how_much)

Операция записи в файл. Указатель what задает начало буфера данных; третий параметр указывает, сколько данных надо записать. Система записывает требуемое число байтов в файл, начиная с указателя чтения/записи в этом файле, заменяя хранившиеся в этом месте данные, и перемещает указатель к концу записанного блока. Если файл кончился раньше, его длина увеличивается. Операция возвращает количество записанных байтов. Если файл открывался только для чтения, вызов write возвратит ошибку.

int ioctl ( int handle, int cmd, .. . .)

int fcntl(int handle, int cmd, . . . )

Дополнительные операции над файлом. Первоначально, по-видимому, предполагалось, что ioctl — это операции над самим файлом, a fcntl — это операции над дескриптором открытого файла, но потом историческое развитие несколько перемешало функции этих системных вызовов. Стандарт POS1X определяет некоторые операции как над дескриптором, например дублирование (в результате этой операции мы получаем два дескриптора, связанных с одним и тем же файлом), так и над самим файлом, например, операцию truncate — обрезать файл до заданной длины. В большинстве версий Unix операцию truncate можно использовать и для вырезания данных из середины файла. При считывании данных из такой вырезанной области считываются нули, а сама эта область не занимает физического места на диске.

Важной операцией является блокировка участков файла. Стандарт POSIX предлагает для этой цели библиотечную функцию, но в системах семейства Unix эта функция реализована через вызов fcntl.

Большинство реализаций стандарта POSIX предлагает и свои дополнительные операции. Так, в Unix SVR4 этими операциями можно устанавливать

синхронную или отложенную запись (Подробнее понятие отложены записи обсуждается в разд. Асинхронная модель ввода-вывода с точки зрения приложений) и т. д.

caddr t mmap(cadclr t addr, size_t len, int prot, int flags, int handle, off_t

Отображение участка файла в виртуальное адресное пространство процесса. Параметр prot задает права доступа к отображенному участку: на чтение, запись и исполнение. Отображение может происходить на заданный виртуальный адрес, или же система может выбирать адрес для отображения сама.

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

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

Примерно та же модель работы с файлами принята в СР/М, а набор файловых системных' вызовов MS DOS фактически скопирован с вызовов Unix v7. В свою очередь, OS/2 и Windows NT/2000/XP унаследовали принципы работы с файлами непосредственно от MS DOS.

В системах, не имеющих Unix в родословной, может использоваться несколько иная трактовка понятия файла. Чаще всего файл трактуется как набор записей (рис. 11.4). Обычно система поддерживает записи как постоянной длины, так и переменной. Например, текстовый файл интерпретируется как файл с записями переменной длины, а каждой строке текста соответствует одна запись. Такова модель работы с файлами в VMS и в ОС линии OS/360-MVS-z/OS фирмы IBM.

Практика систем с неструктурированными файлами показала, что, хотя структурированные файлы часто бывают удобны для программиста, необязательно встраивать поддержку записей в ядро системы. Это вполне можно сделать и на уровне библиотек. К тому же структурированные файлы сами по себе не решают серьезной проблемы, полностью осознанной лишь в 80-е годы при разработке новых моделей взаимодействия человека с компьютером.

Рис. 11.4. Неструктурированный файл и файлы как наборы записей



Простые файловые системы


Простые файловые системы

Наиболее простой файловой системой можно считать структуру, создаваемую архиватором системы UNIX — программой tar (Tape ARchive — архив на [магнитной] ленте). Этот архиватор просто пишет файлы один за другим помещая в начале каждого файла заголовок с его именем и длиной (рис. 11.5). Аналогичную структуру имеют файлы, создаваемые архиваторами типа arj; в отличие от них, tar не упаковывает файлы.

Рис. 11.5. Структура архива tar

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

Для того чтобы не заниматься при каждом новом поиске просмотром всего устройства, удобнее всего разместить каталог в определенном месте, например в начале ленты. Наиболее простую, из знакомых автору, файловую систему такого типа имеет ОС RT-11. Это единственная известная автору файловая система, которая с одинаковым успехом применялась как на лентах, так и на устройствах с произвольным доступом. Все более сложные ФС, обсуждаемые далее, используются только на устройствах произвольного доступа. В наше время наиболее распространенный тип запоминающего устройства произвольного доступа — это магнитный или оптический диск, поэтому далее в тексте мы будем называть такие устройства просто дисками — для краткости, хотя такое сокращение и не вполне корректно.

В этой ФС, как и во всех обсуждаемых далее, место на диске или ленте выделяется блоками. Размер блока, как правило, совпадает с аппаратным размером сектора (512 байт у большинства дисковых устройств), однако многие фС могут использовать логические блоки, состоящие из нескольких секторов (так называемые кластеры).

Использование блоков и кластеров вместо адресации с точностью до байта обусловлено двумя причинами. Во-первых, у большинства устройств произвольного доступа доступ произволен лишь с точностью до сектора, т. е. нельзя произвольно считать или записать любой байт — нужно считывать или записывать весь сектор целиком. Именно поэтому в системах семейства Unix такие устройства называются блочными (block-oriented).

Во-вторых, использование крупных адресуемых единиц позволяет резко увеличить адресуемое пространство. Так, используя 16-битный указатель, с точностью до байта можно адресовать всего 64 Кбайт, но если в качестве единицы адресации взять 512-байтовый блок, то объем адресуемых данных сможет достичь 32 Мбайт; если же использовать кластер размером 32 Кбайт, то можно работать с данными объемом до 2 Гбайт. Аналогично, 32-битовый указатель позволяет адресовать с точностью до байта 4 Гбайт данных, т. е. меньше, чем типичный современный жесткий диск; но если перейти к адресации по блокам, то адресное пространство вырастет до 2 Тбайт, что уже вполне приемлемо для большинства современных запоминающих устройств.

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

Ряд современных файловых систем использует механизм, по-английски называемый block siiballocation, т. е. размещение частей блоков. В этих ФС кластеры имеют большой размер, но есть возможность разделить кластер на несколько блоков меньшего размера и записать в эти блоки "хвосты" от нескольких разных файлов (рис. 11.6). Это, безусловно, усложняет ФС, но позволяет одновременно использовать преимущества, свойственные и большим, и маленьким блокам. Поэтому ряд распространенных ФС, например файловая система Novell Netware 4.1 и FFS (известная также как UFS и Berkley FS), используемая во многих системах семейства Unix, применяе этот механизм.

Рис. 11.6. Субаллокация блоков

Субаллокация требует от файловой системы поддержания запаса свободных блоков на случай, если пользователю потребуется увеличить длину одного из файлов, "хвост" которого был упакован во фрагментированный блок. Учебные пособия по Netware рекомендуют поддерживать на томах с субаллокацией не менее тысячи свободных кластеров, но не предоставляют штатных методов обеспечения этого требования. Напротив, UFS показывает свободное место на диске с учетом "неприкосновенного" резерва свободного пространства, так что нулевое показываемое свободное пространство соответствует 5% или 10% физического свободного места. Объем этого резерва настраивается утилитами конфигурации ФС.

Но вернемся к простым файловым системам. В RT-11 каждому файлу выделяется непрерывная область на диске. Благодаря этому в каталоге достаточно хранить адрес первого блока файла и его длину, также измеренную в блоках. В RT-11 поступили еще проще: порядок записей в каталоге совпадает с порядком файлов на диске, и началом файла считается окончание предыдущего файла. Свободным участкам диска тоже соответствует запись в каталоге (рис. 11.7). При создании файла система ищет первый свободный участок подходящего размера.

Фактически эта структура отличается от формата tar только тем, что каталог вынесен в начало диска, и существует понятие свободного участка внутри области данных. Эта простая организация имеет очень серьезные недостатки.

1. При создании файла программа должна указать его длину. Часто это бывает затруднительно. Особенно неудобно увеличивать размер уже созданного файла. Точнее, это просто невозможно: вместо удлинения старого файла приходится создавать новый файл нужной длины и копировать содержимое старого файла в него.

2. При хаотическом создании и удалении файлов возникает проблема фрагментации свободного пространства. Для ее решения существует специальная программа SQUEESE (сжать [диск]), которая переписывает файлы г так, чтобы объединить все свободные фрагменты (рис. 11.8). Эта программа требует много времени, особенно для больших дисковых томов, и потенциально опасна: если при ее исполнении произойдет сбой системы (а с машинами третьего поколения такое случалось по нескольку раз в день), то значительная часть данных будет необратимо разрушена.

Рис. 11.7. Структура файловой системы RT-11

Рис. 11.8. Дефрагментация диска в RT-11

Для того чтобы решить обе эти проблемы, необходимо позволить файлам занимать несмежные области диска. Наиболее простым решением было бь хранить в конце каждого блока файла указатель на следующий, т. е. превра тить файл в связанный список блоков (рис. 11.9). При этом, естественно в каждом блоке хранить не 512 байт данных, а на 2 — 4 байта меньше. При строго последовательном доступе к файлу такое решение было бы впотне приемлемым, но при попытках реализовать произвольный доступ возникнут неудобства. Возможно, поэтому, а может и по каким-то исторически сложившимся причинам такое решение не используется ни в одной из известных автору ОС.

Рис. 11.9. Файл в виде односвязного списка блоков

Отчасти похожее решение было реализовано в MS DOS и DR DOS. Эти системы создают на диске таблицу, называемую FAT (File Allocation Table, таблица размещения файлов). В этой таблице каждому блоку, предназначенному для хранения данных, соответствует 12-битовое значение. Если блок свободен, то значение будет нулевым. Если же блок принадлежит файлу, то значение равно адресу следующего блока этого файла. Если это последний блок в файле, то значение — OxFFF (рис. 11.10). Существует также специальный код для обозначения плохого (bad) блока, не читаемого из-за дефекта физического носителя. В каталоге хранится номер первого блока и длина файла, измеряемая в байтах.

Емкость диска при использовании 12-битовой FAT оказывается ограничена 4096 блоками (2 Мбайт), что приемлемо для дискет, но совершенно не годится для жестких дисков и других устройств большой емкости. На таких устройствах DOS использует FAT с 16-битовыми элементами. На еще больших (более 32 Мбайт) дисках DOS выделяет пространство не блоками. а кластерами из нескольких блоков. Эта файловая система так и называется - FAT.

Она очень проста и имеет одно серьезное достоинство: врожденную устойчивость к сбоям (fault tolerance), но об этом далее. В то же время у нее есть и ряд серьезных недостатков.

Рис. 11.10. Структура файловой системы FAT

Первый недостаток состоит в том, что при каждой операции над файлами система должна обращаться к FAT. Это приводит к частым перемещениям головок дисковода и в результате к резкому снижению производительности. Действительно, исполнение программы arj на одной и той же машине под MS DOS и под DOS-эмулятором систем Unix или OS/2 различается по скорости почти в 1,5 раза. Особенно это заметно при архивировании больших каталогов.

Использование дисковых кэшей, а особенно помещение FAT в оперативную память, существенно ускоряет работу, хотя обычно FAT кэшируется только для чтения ради устойчивости к сбоям. При этом мы сталкиваемся со специфической проблемой: чем больше диск, тем больше у него FAT, соответственно, тем больше нужно памяти. У тома Novell Netware 3.12 размером 1,115 Гбайт с размером кластера 4 Кбайт размер FAT достигает мегабайта (легко понять, что Netware использует FAT с 32-разрядными элементами. При 16-разрядном элементе FAT дисковый том такого объема с таким размером кластера просто невозможен). При монтировании такого тома Netware занимает под FAT и кэш каталогов около 6 Мбайт памяти.

Для сравнения, Netware 4 использует субаллокацию, поэтому можно относительно безнаказанно увеличивать объем кластера и нет необходимости делать кластер таким маленьким. Для дисков такого объема Netware 4 устанавливает размер кластера 16 Кбайт, что приводит к уменьшению всех структур данных в 4 раза. Понятно, что для MS DOS, которая умеет адресовать всего 1 Мбайт (1088 Кбайт, если разрешен НМА), хранить такой FAT в памяти целиком просто невозможно.

Разработчики фирмы MicroSoft пошли другим путем: они ограничили разрядность элемента FAT 16 битами. При этом размер таблицы не может превышать 128 Кбайт, что вполне терпимо. Зато вся файловая система может быть разбита только на 64 Кбайт блоков. В старых версиях MS DOS это приводило к невозможности создавать файловые системы размером 32 Мбайт.

В версиях старше 3.11 появилась возможность объединять блоки в кластеры Например, на дисках размером от 32 до 64 Мбайт кластер будет состоять из 2 блоков и иметь размер 1 Кбайт. На дисках размером 128—265 Мбайт кластер будет уже размером 4 Кбайта и т. д.

Windows 95 использует защищенный режим процессора х86, поэтому адресное пространство там гораздо больше одного мегабайта. Разработчики фирмы Microsoft решили воспользоваться этим и реализовали версию FAT с 32-битовым элементом таблицы — так называемый FAT32. Однако дисковый кэш Windows 95 не стремится удержать весь FAT в памяти; вместо этого FAT кэшируется на общих основаниях, наравне с пользовательскими данными. Поскольку работа с файлами большого (больше одного кластера) объема требует прослеживания цепочки элементов FAT, а соответствующие блоки таблицы могут не попадать в кэш, то производительность резко падает. В сопроводительном файле Microsoft признает, что производительность FAT32 на операциях последовательного чтения и записи может быть в полтора раза ниже, чем у кэшированного FAT 16.

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

Для эффективного управления большими объемами данных необходимо что-то более сложное, чем FAT.



"Сложные" файловые системы


"Сложные" файловые системы

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

Обычно файловая система начинается с заголовка, или, как это называется в системах семейства Unix, суперблока (superblock). Суперблок хранит информацию о размерах дискового тома, отведенного под ФС, указатели на начало системных структур данных и другую информацию, зависящую от типа ФС. Например, для статических структур может храниться их размер. Часто суперблок содержит также магическое число — идентификатор типа файловой системы. Аналог суперблока существует даже в FAT — это так называемая загрузочная запись (boot record).

Практически все современные ФС разделяют список свободных блоков и структуры, отслеживающие размещение файлов. Чаще всего вместо списка свободных блоков используется битовая карта, в которой каждому блоку соответствует один бит: занят/свободен. В свою очередь, список блоков для каждого файла обычно связан с описателем файла. На первый взгляд, эти описатели кажется естественным хранить в каталоге, но их, как правило, выносят в отдельные области, часто собранные в специальные области диска — таблицу инодов, метафайл и т. д. Такое решение уменьшает объем каталога и, соответственно, ускоряет поиск файла по имени. К тому же многие ФС сортируют записи в каталоге по имени файла, также с целью ускорения поиска. Понятно, что сортировка записей меньшего размера происходит быстрее.

В файловой системе HPFS, используемой в OS/2 и Windows NT, каждая запись в каталоге содержит имя файла и указатель vtajhode (файловую запись). Каталоги в этой ФС организованы в виде В-деревьев и отсортированы по именам файлов.

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

Нужно отметить, что идея экстентов далеко не нова: аншюгичная структура используется в некоторых версиях Unix с начала 80-х годов, а истоки этой идеи теряются в глубине 60-х.

Файловая запись обычно размещается перед началом первого экстента файла, хотя это и не обязательно. Она занимает один блок (512 байт) и может содержать до десяти описателей экстентов (рис. 11.11). Кроме того, она содержит информацию о времени создания файла, его имени и расширенных атрибутах (см. разд. Тип файла). Если для списка экстентов или расширенных атрибутов места не хватает, то для них также выделяются экстенты. В этом случае экстенты размещаются в виде В-дерева для ускорения поиска. Максимальное количество экстентов в файле не ограничено ничем, кроме размера диска.

Пользовательская программа может указать размер файла при его создании. В этом случае система сразу попытается выделить место под файл так, чтобы он занимал как можно меньше экстентов. Если программа не сообщила размера файла, используется значение по умолчанию. Фактически, HPFS размещает место под файл по принципу worst fit (наименее подходящего), начиная выделение с наибольшего непрерывного участка свободного пространства. В результате фрагментированными оказываются только файлы, длина которых увеличивалась многократно или же те, которые создавались при почти заполненном диске. При нормальной работе файл редко занимает больше 3—4 экстентов.

Рис. 11.11. Каталог и файловая запись в HPFS

Еще одно любопытное следствие применения стратегии worst fit заключается в том, что пространство, освобожденное стертым файлом, обычно используется не сразу. Отмечались случаи, когда файл на активно используемом диске удавалось восстановить через несколько дней после стирания.

Экстенты открытых файлов и карта свободных блоков во время работы размещаются в ОЗУ, поэтому производительность такой ФС в большинстве ситуаций намного (в 1,5—2 раза и более) выше, чем у FAT с тем же объемом кэша, при вполне приемлемых потребностях в памяти и размере кластера 512 байт.

Видно также, что структура HPFS упрощает произвольный доступ к файлу: вместо прослеживания цепочки блоков нам нужно проследить цепочку экстентов, которая гораздо короче.

Более подробное описание структуры HPFS можно найти в статье [PC Magazine 1995|. Пользователи OS/2 считают целесообразным форматировать все разделы емкостью более 12SM под HPFS, поскольку при этом выигрывается скорость и увеличивается эффективность использования дискового пространства; кроме того, исчезает необходимость в дефрагментацин и появляется возможность создавать файлы и каталоги с длинными именами, не укладывающимися в модель 8.3, принятую в MS DOS.

За эти преимущества приходится платить неустойчивостью к сбоям (проблема устойчивости к системным сбоям обсуждается в разд. Устойчивость ФС к сбоям). В отличие от ДОС, спонтанные разрушения системы с последующим зависанием в OS/2 случаются относительно редко, даже при запуске программ, заведомо содержащих ошибки (как при разработке или тестировании прикладного программного обеспечения). С другой стороны, на практике "неустойчивость" приводит лишь к тому, что после аварийной перезагрузки автоматически запускается программа восстановления ФС, что увеличивает время перезагрузки в несколько раз; реальный же риск потерять данные при сбое не выше, а как показывает практика, даже существенно ниже, чем при использовании FAT, поэтому игра явно стоит свеч.

Наиболее интересна структура файловых систем в ОС семейства Unix. В этих ФС каталог не содержит почти никакой информации о файле. Там хранится только имя файла и номер его инода (i-node — по-видимому, сокращение от index node: индексная запись). Иноды всех файлов в данной ФС собраны в таблицу, которая так и называется: таблица инодов. В ранних версиях Unix таблица инодов занимала фиксированное пространство в начале устройства; в современных файловых системах эта таблица разбита на участки, распределенные по диску.

Например, в файловой системе BSD Unix FFS (Fast File System — быстрая файловая система), которая в Unix SVR4 называется просто UFS (Unix File System), диск разбит на группы цилиндров. Каждая группа цилиндров содержит копию суперблока, битовую карту свободных блоков для данного участка и таблицу инодов для файлов, расположенных в пределах этого участка (рис. 11.12). Такая распределенная структура имеет два преимущества.

Ускорение доступа к системным структурам данных. Когда системные данные расположены вблизи от блоков пользовательских данных, уменьшается расстояние, на которое перемещаются головки дисковода.

Повышенная устойчивость к сбоям носителя. При повреждении участка поверхности диска теряется только небольшая часть системных данных. Даже потеря суперблока не приводит к потере структуры файловой системы.

Рис. 11.12. Блоки цилиндров FFS

Инод хранит информацию о самом файле и его размещении на диске (рис. 11.13, пример 11.2). Информационная часть инода может быть получена системным вызовом

int stat(const char * fname, struct stat * buf) ;

Формат структуры stat описан во многих руководствах по языку С. ОС UNIX и стандарту POSIX, например, в работе (Керниган-Ритчи 2000|. Эта структура содержит следующую информацию.

Тип файла. Исследуя это поле, можно понять, является данный объект файлом данных или специальным файлом. В этом же поле закодированы права доступа к файлу.

Идентификаторы владельца файла и группы. Вместе с правами доступа эти два идентификатора образуют список контроля доступа файла (см разд. Списки контроля доступа).

Время:

создания файла;

последней модификации файла;

последнего доступа к файлу.

Длина файла. Для специальных файлов это поле часто имеет другой смысл.

Идентификатор файловой системы, в которой расположен файл.

Количество связей файла. Это поле заслуживает отдельного обсуждения.

Рис. 11.13. Каталоги и иноды файловых систем семейства Unix

Пример 11.2. Структура инода файловой системы ext2fs

/* * Структура данных инода second extended file system, считанная в память

*/

i- struct ext2_inode_info { _u32 i_data[15]; _ u32 i_flags; _u32 i^faddr; _ u8 i_frag_no; _ u8 i_f rag_size; _ u!6 i_osync; _ u32 i_file_acl; _ u32 i_dir_acl; _ u32 i_dtime;

_ u32 not_used_l; /* FIX: не используется/зарезервировано для 2.2 */ _ u32 i_block_group; _ u32 i_next_alioc_block;

u32 i next alloc goal; _ u32 i_prealloc_block;

u32 i prealloc count; __ u32 i_high_size;

int i_new _inode : 1 ; /* Этот инод только что вьделен */

Структура, описывающая физическое размещение файла на диске, недоступна пользовательским программам. Собственно, формат этой структуры может быть не очень элегантен. Например, в файловой системе Veritas это список экстентов, похожий на HPFS; в файловых системах s5, Xenix и FFS это массив из 13 чисел, задающих номера физических блоков файла. Если файл в s5 содержит более десяти блоков (т. е. его длина больше 5 Кбайт), то предпоследние три указателя обозначают не блоки данных, а так называемые косвенные блоки (indirection blocks), в которых хранятся указатели на следующие блоки данных и, возможно, на следующие косвенные блоки.

Наиболее интересная особенность ФС семейства Unix состоит не в этом. Внимательный читатель, возможно, заметил, что инод не содержит имени файла. С другой стороны, он содержит счетчик связей (link) — ссылок на этот файл из каталогов. Таким образом, на один и тот же инод можно ссылаться из различных каталогов или из одного каталога под разными именами (рис. 11.14). Иными словами, один и тот же файл в этих ФС может иметь несколько различных имен. Именно это и имелось в виду, когда го верилось, что структура каталогов в ОС UNIX не обязана быть деревом.

Это свойство предоставляет неоценимые возможности для организации не рархии каталогов, но имеет и некоторые оборотные стороны.

1. Создание нескольких связей для каталога потенциально опасно— оно может привести к возникновению кольца, в котором каталог является своим собственным подкаталогом. Отслеживать такую ситуацию сложно поэтому разработчики ОС UNIX запретили создавать дополнительные имена для каталогов.

2. Удаление файла превращается в проблему: чтобы удалить файл, нужно проследить все его связи. Поэтому UNIX не имеет средств для удатсния файла, а обладает только системным вызовом unlink — удалить связь. Когда у файла не остается связей, он действительно удаляется. Этот подход вполне разумен, но также имеет неожиданную оборотную сторону: поскольку теперь стирание файла — это операция не над файлом, а над каталогом, то для удаления файла не нужно иметь никаких прав доступа к нему. Достаточно иметь право записи в каталог.

На практике, механизм защиты от стирания отдельных файлов предусмотрен — при установке в атрибутах каталога так называемого sticky bit ("липкий бит"), система запрещает стирать файлы, для которых вы не имеете права записи, но и этот механизм не лишен недостатков.

3. Такие связи (называемые еще жесткими (hard) связями), как легко понять, могут создаваться только в пределах одной файловой системы, поскольку каждая ФС имеет собственную таблицу инодов, и соответственно собственную их нумерацию.

Рис. 11.14. Жесткие связи в Unix

Последнее обстоятельство резко уменьшает полезность жестких связей для организации иерархии каталогов. Эта проблема была осознана еще в 70-е годы, и программисты из группы BSD придумали интересное новое понятие - символическую связь (symbolic link) илиsymlink.

Символическая связь представляет собой специальный файл. Вместо блоков данных инод такого файла содержит текстовую строку — имя того файла, с которым создана связь (рис. 11.15). Это может быть файл из другой файловой системы, в том числе и из такой, которая сама по себе не поддерживает ни жестких, ни символических связей, например, FAT, HPFS или файловый сервер Novell Netware. Такого файла может и вообще не существовать, например, потому, что его уже удалили, или потому, что файловая система, в которой он находится, не смонтирована, или просто потому, что имя было задано неправильно. Тогда попытки открыть символическую связь будут завершаться неудачей с кодом ошибки "файла не существует".


Рис. 11.15. Символическая связь

Единственным недостатком символических связей является их относительно низкая "дуракоустойчивость" (fool-tolerance): глупый пользователь может не распознать ситуации, когда символическая связь указывает в никуда. Зато они обеспечивают полную свободу в размещении и именовании файлов.

Пример из жизни

На двух Unix-системах с именами orasrv и Indy установлен один и тот же программный продукт: редакторная система GNU Emacs. Бинарные загрузочные модули для этих систем различаются, но большая часть Emacs — это файлы на языке Emacs Lisp, которые с одинаковым успехом могут использоваться обеими системами. Поэтому у администратора системы возникает желание использовать одну копию lisp-файлов. При этом Emacs установлена таким обра зом, что она ищет все свои lisp-файлы в каталоге /usr/local/lib/emacs/19.27/lisp Изменение этого каталога потребовало бы частичной переустановки продукта Но его не надо менять! Мы просто подмонтируем на машине orasrv каталог / машины Indy как /fs/lndy и исполняем следующие команды примера 11.3.

Пример 11.3. Перенос каталога без изменения его путевого имени

cd /usr/local/lib/emacs/19.27 # перейти в заданный каталог rm -Rf lisp

# стереть каталог lisp со всем содержимым

In -s /fs/Indy/usr/local/lib/emacs/19.27/lisp lisp

# создать символическую связь с именем lisp с соответствующим

# каталогом на машине Indy

Вся операция вместе с ее планированием занимает около двух минут. Освобождается около 9 Мбайт дискового пространства. Emacs ничего не замечает, и работает без всяких проблем.

Через неделю у администратора возникает идея, что для удобства администрирования неплохо было бы монтировать с orasrv не всю файловую систему Indy, а только ее каталог /home. За чем дело стало: переносим на Indy каталог lisp в каталог /home/emacs/19.27/lisp; создаем в старом каталоге символическую связь с новой; редактируем файл /etc/mnttab на-машине orasrv так, чтобы с Indy монтировался только /home; меняем символическую связь каталога lisp на машине orasrv. Заставляем orasrv подмонтировать диски в соответствии с новым /etc/mnttab. Готово.

Операция занимает чуть больше двух минут, потому что нужно переносить 9 Мбайт из одной файловой системы в другую. Emacs опять ничего не замечает и снова работает без всяких проблем. Администратор счастлив. Все довольны. Сравните это описание с впечатлениями пользователя, который пытается переместить с одного ДОС-вского драйва на другой типичную программу для Win32, которая при установке записывает во многие места своей конфигурации и системного реестра полное имя каталога, в который ее ставили...

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

Жесткие связи в VMS и Windows NT/2000/XP

Например, в файловой системе VAX/VMS данные о размещении файлов на диске хранятся в специальном индексном (index) файле; каталоги же хранят только индексы записей в этом файле. Основное отличие этой структуры от принятой в Unix состоит в том, что вместо статической таблицы или набора таблиц используется динамическая таблица, пространство для которой выделяется тем же методом, что и для пользовательских файлов. Этот же подход реализован в файловой системе NTFS, используемой в Windows NT/2000/XP, но в ней индексный файл называется MFT (Main File Table — главная таблица файлов). Более подробное описание структуры NTFS приводится в статье [www.digit-life.com NTFS].

VAX/VMS и Windows NT позволяют создавать дополнительные имена для файлов, хотя в VMS утилиты восстановления ФС выдают предупреждение, обнаружив такое дополнительное имя. Все имена файла в этих ФС обязаны находиться в одной файловой системе. Кроме того, операция удаления файла в VMS ведет себя не так, как в Unix: применение операции удаления к любому из имен приводит к удалению самого файла, даже если существовали и другие имена.



Тип файла


Тип файла

Легко понять, что структурированные файлы предоставляют системе и программисту информацию о структуре хранящихся данных, но не дают никаких сведений о форме представления и смысле этих данных.

Например, с точки зрения системы исходный текст программы на языке С

и документ в формате LATEX совершенно идентичны: и то, и другое представляет собой текстовый файл (или, если угодно, файл с записями переменной длины). Однако, если мы попытаемся подать наш документ на вход С-компилятора, мы получим множество синтаксических ошибок и никакого Полезного результата.

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

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

Так, например Explorer — пользовательская оболочка Windows 95 и Windows NT 4.0 — позволяет связать ту или иную программу с файлами, имеющими определенное расширение, например, программу MS Word с файлами имеющими расширение DOC. Когда пользователь нажимает левую кнопку мыши на значке, представляющем такой файл, то автоматически запускается MS Word. Эти же ассоциации доступны и из командной строки — можно напечатать start Доклад. DOC, и опять-таки запустится MS Word.

Такое связывание очень просто в реализации и сделано не только в Explorer, но и в простых текстовых оболочках вроде Norton Commander. От ОС при этом требуется только дать возможность каким-то образом различать типы файлов.

Первые попытки ассоциировать с файлом признак типа были сделаны еще в 60-е годы. При этом идентификатор типа добавлялся к имени файла в виде короткой, но мнемонической последовательности символов — расширения (extension). В большинстве современных ОС расширение отделяется от имени символом ".", но проследить истоки этой традиции автору не удалось. При этом, например, файлы на языке С будут иметь расширение "с", на

C++ — "С", а документы в формате LATEX — "tex".

В ОС семейства Unix имя файла может содержать несколько символов ".", и, таким образом, файл может иметь несколько каскадированных расширений. Например, файл "main.С" — это программа на языке C++; "main.C.gz" — это программа на языке C++, упакованная архиватором GNU Zip с целью сэкономить место; "main.C.gz.crypt" — это программа, которую упаковали и потом зашифровали, чтобы никто посторонний не смог ее прочитать; наконец, "main.C.gz.crypt.uue" — это упакованная и зашифрованная программа, преобразованная в последовательность печатаемых символов кода ASCII, например, для пересылки по электронной почте.

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

Пример 11.1. Командная строка компилятора

ее main.С c-code.c asm-code.s obj-code.o\ libraryl.a Iibrary2.so -o program

Например, стандартный драйвер компилятора в системах семейства Unix — программа со — определяет тип файла именно по расширению. Командная строка, приведенная в примере 11.1, будет интерпретироваться следующим образом.

main.С — текст на языке C++. Его нужно обработать препроцессором и откомпилировать компилятором C++, а затем передать то, что получится, редактору связей. Большинство компиляторов в Unix генерируют код на ассемблере, т. е. вывод компилятора еще нужно пропустить через ассемблер.

c-code.c — текст на языке С. Он обрабатывается так же, как и программа на С ++, только вместо компилятора C++ используется компилятор С.

asm-code.s — программа на языке ассемблера. Ее нужно обработать ассемблером и получить объектный модуль.

obj-code.o — объектный модуль, который непосредственно можно передавать редактору связей.

library1.a — объектная библиотека, которую нужно использовать для разрешения внешних ссылок наравне со стандартными библиотеками.

library2.so — разделяемая библиотека, которую надо связать с создаваемым динамическим модулем.

Многие ОС, разработанные в 70-е годы, такие как RT-11, RSX-11, VAX/VMS, CP/M, навязывают программисту разделение имени на собственно имя и расширение, интерпретируя точку в имени файла как знак препинания. В таких системах имя может содержать только одну точку и соответственно иметь только одно расширение. Напротив, в ОС нового поколения — OS/2, Windows NT и даже в Windows 95 — реализована поддержка имен файлов свободного формата, которые могут иметь несколько каскадированных расширений, как и в Unix.

Однако никакие средства операционной системы не могут навязать прикладным программам правил выбора расширения для файлов данных. Это приводит к неприятным коллизиям. Например, почти все текстовые процессоры от Лексикона до Word 2000 включительно используют расширение Файла .doc (сокращение от document), хотя форматы файлов у различных процессоров и даже у разных версий одного процессора сильно различаются.

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

Так, VMS и системы семейства СР/М используют расширение .ехе: сокращение от executable (исполняемый). Однако по мере развития системы формат загрузочного модуля может изменяться. Так, например, OS/2 v3.0 поддерживает по крайней мере шесть различных форматов загрузочных модулей.

16-разрядные сегментированные загрузочные модули: формат OS/2 х

32-разрядные загрузочные модули, использующие "плоскую" (flat) модец, памяти: формат OS/2 2.x (LE — Linear Executable).

32-разрядные модули нового формата, использующие упаковку кода данных: формат OS/2 3.x (LX — Linear executable extended).

ехе- и corn-модули DOS.

Загрузочные модули Win 16 (NE).

Загрузочные модули Win32s (РЕ — Portable Executable).

Для исполнения последних трех типов программ OS/2 создает виртуальную машину, работающую в режиме совместимости с 8086. Эта задача запускает копию ядра DOS и, если это необходимо, копию MS Windows, которые уже выполняют загрузку программы. Загрузочные модули всех трех "родных" форматов загружаются системой непосредственно. Так или иначе, загрузчик должен уметь правильно распознавать все форматы. При этом он не может использовать расширение файла: файлы всех перечисленных форматов имеют одинаковое расширение ЕХЕ.

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

Разработчики Unix столкнулись с этой проблемой еще в 70-е годы. В качестве решения они предложили использовать магические числа (magic number) или сигнатуры (signature— подпись) — соглашение о том, что файлы определенного формата содержат в начале определенный байт или последовательность байтов. Первоначально это были численные коды; файл /etc/magic содержал коды, соответствующие известным типам файлов. Позднее в качестве магических чисел стали использоваться длинные текстовые строки. Так, например, изображения в формате CompuServe GIF 87а должны начинаться с символов GIF87a.

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

С длинными мнемоническими текстовыми строками связана еще одна забавная проблема, которая может иметь неприятные последствия. Например-текстовый файл следующего содержания:

GIF87a — это очень плохой формат хранения изображений. Он будет воспринят некоторыми программами как изображение в формате CompuServe (GIF 87а, каковым он, безусловно, не является.

Оригинальное развитие идея магических чисел получила в современных системах семейства Unix, где сигнатура вида #!/bin/sh означает, что данный файл представляет собой интерпретируемую программу, интерпретатор которой хранится в файле /bin/sh (в данном случае это стандартный командный процессор).

Пытаясь как-то решить проблему идентификации типа файла, разработчики Macintoch отказались как от расширений, так и от магических чисел. В MacOS каждый файл состоит из двух частей или ветвей (forks): ветви данных (data fork) и ветви ресурсов (resource fork). Кроме идентификатора типа файла, ветвь ресурсов хранит информацию о:

значке, связанном с этим файлом;

расположении значка в открытой папке (folder);

программе, которую нужно запустить при "открытии" этого файла.

Еще дальше в этом же направлении пошли разработчики системы OS/2. В этой системе с каждым файлом связан набор расширенных атрибутов (extended attributes). Атрибуты имеют вид "ИМЯ:Значение". При этом значение может быть как текстовой строкой, так и блоком двоичных данных произвольного формата и размера. Некоторые расширенные атрибуты используются оболочкой Workplace Shell (WPS) как эквивалент ветви ресурсов в MacOS: для идентификации типа файла, связанного с ним значка и размещения этого значка в открытом окне. Тип файла идентифицируется текстовой строкой. Например, программа на языке С идентифицируется строкой С code. Это резко уменьшает вероятность конфликта имен типов — ситуацию, довольно часто возникающую при использовании расширений или магических чисел.

Другие атрибуты могут применяться для других целей. Например, LAN Server — файловый сервер фирмы IBM — использует расширенные атрибуты для хранения информации о владельце файла и правах доступа к нему. Некоторые текстовые редакторы применяют расширенные атрибуты для хранения положения курсора при завершении последней сессии редактирования, так что пользователь всегда попадает в то место, где он остановился в прошлый раз.

Кроме того, расширенные атрибуты могут использоваться и для хранения сведений о назначении файла. В OS/2 существуют предопределенные расширенные атрибуты с именами subject (тема), comment (комментарии) и Key phrases (ключевые фразы), которые могут, например, использоваться для поиска документов, относящихся к заданной теме. К сожалению, такой поиск возможен, только если создатель документа позаботился о присвое нии этим атрибутам правильных значений.



Устойчивость ФС к сбоям


Устойчивость ФС к сбоям

Свойство устойчивости к сбоям питания (power-fault tolerance) является одной из важных характеристик файловой системы. Строго говоря, имеется в виду устойчивость не только к сбоям питания, но и к любой ситуации, при которой работа с ФС прекращается без выполнения операции размонтирования. Поэтому правильнее было бы говорить об устойчивости к любым сбоям системы, а не только питания.

С другой стороны, если говорить просто об "устойчивости к сбоям", возникает неприятная двусмысленность. Под устойчивостью к сбоям можно понимать устойчивость к сбоям всей системы, например, к тем же сбоям питания, а можно понимать устойчивость к дефектам физического носителя, которые могут привести к потере части данных на диске. Вторая проблема обычно решается с помощью механизма горячей замены (логической переадресации) сбойных блоков, который обсуждается к разд. Устойчивость ФС к сбоям, а сейчас мы будем говорить только о первой проблеме, называя ее просто "устойчивостью" для краткости.



Устойчивость ФС к сбоям диска


Устойчивость ФС к сбоям диска

Кроме общесистемных сбоев, ФС должна обеспечивать средства восстановления при физических сбоях диска. Наиболее распространенным видом таких сбоев являются нечитаемые — "плохие" (bad) — блоки, появление которых обычно связано с физическими дефектами магнитного носителя.

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

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

Весьма опасной причиной порчи жестких дисков является соприкосновение головок чтения/записи с поверхностью вращающегося диска (head crash) например, из-за чрезмерно сильных сотрясений диска во время работы В частности, из-за этого не следует переставлять работающие компьютеры особенно во время активных операций с диском. Обычно такое соприкосновение приводит к повреждению целой дорожки или нескольких дорожек диска, а зачастую и самой головки. Для несъемных жестких дисков это нередко означает потерю целой рабочей поверхности: считывание данных с нее требует замены блока головок, что весьма дорого.

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

В файловой системе FAT плохой блок или кластер, содержащий такой блок, отмечается кодом OxFFB или OxFFFB для дисков с 16-разрядной FAT. Эта файловая система не способна компенсировать плохие блоки в самой FAT или в корневом каталоге диска. Такие диски просто считаются непригодными для использования.

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

Современные контроллеры жестких дисков часто предоставляют свои средства горячей замены блоков, происходящие незаметно для центрального процессора.

Рис. 11.25. Горячая замена (динамическое переназначение) блоков диска

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

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

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

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



Устойчивость к сбоям питания


Устойчивость к сбоям питания

На самом деле, неожиданное прекращение работы с ФС может произойти не только при сбое питания, но и в следующих ситуациях:

извлечении носителя из дисковода (подробнее об этом см. далее);

нажатии кнопки RESET нетерпеливым пользователем;

фатальном аппаратном сбое;

аппаратном сбое, который сам по себе не был фатальным, но система не смогла правильно восстановиться, что привело к ее разрушению;

разрушении системы из-за чисто программных проблем.

На практике часто сложно провести границы между тремя последними типами сбоев. В качестве примера можно привести проблему, описанную в разд. Обмен данными с пользовательским процессом. В системах класса ДОС последняя причина возникает очень часто, поэтому в таких системах можно использовать только устойчивые сбоям ФС.

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

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

В системах же реального времени, которые по роду работы могут часто и неожиданно перезапускаться, например, при отладке драйверов или программ, осуществляющих доступ к аппаратуре, стараются использовать устойчивые к сбоям ФС.

Хотя первая из перечисленных выше причин — извлечение носителя из дисковода — не является "сбоем" даже в самом широком смысле этого слова, с точки зрения ФС она мало чем отличается от сбоя. Поэтому на удаляемых носителях, таких, как дискеты, можно использовать только устойчивые ФС.

Интересный альтернативный подход используется в компьютерах Macintosh и некоторых рабочих станциях. У этих машин дисковод не имеет кнопки для извлечения дискеты. Выталкивание дискеты осуществляется программно, подачей соответствующей команды дисководу. Перед подачей такой команды ОС может выполнить нормальное размонтирование ФС на удаляемом диске.

В узком смысле слова "устойчивость" означает лишь то, что ФС после аварийной перезагрузки не обязательно нуждается в восстановлении. Такие ФС обеспечивают целостность собственных структур данных в случае сбоя, но, вообще говоря, не гарантируют целостности пользовательских данных в файлах.

Нужно отметить, что даже если ФС считается в этом смысле устойчивой, некоторые сбои для нее могут быть опасны. Например, если запустить команду DISKOPT на "устойчивой" файловой системе FAT и в подходящий момент нажать кнопку RESET, то значительная часть данных на диске может быть навсегда потеряна.

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

Характерный и очень простой пример: архиватор InfoZip работает над созданием архива. Программа сформировала заголовок файла, упаковала и записала на диск около 50% данных, и в этот момент произошел сбой. В zip-архивах каталог находится в конце архивного файла и записывается туда после завершения упаковки всех данных. Обрезанный в случайном месте zip-файл не содержит каталога и поэтому, безусловно, является безнадежно испорченным. Поэтому при серьезном обсуждении проблемы устойчивости к сбоям говорят не о гарантии целостности пользовательских данных, а об уменьшении вероятности их порчи.

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

Упоминавшаяся выше "врожденная" устойчивость к сбоям файловой системы FAT объясняется тем, что в этой ФС удаление блока из списка свободных и выделение его файлу производится одним действием — модификацией элемента FAT (рис. 11.16). Поэтому если во время этой процедуры произойдет сбой или дискета будет вынута из дисковода, то ничего страшного не случится: просто получится файл, которому выделено на один блок больше, чем его длина, записанная в каталоге. При стирании этого файла все его блоки будут помечены как свободные, поэтому вреда практически нет.

Рис. 11.16. Модификация FAT

Нужно отметить, что при активном использовании отложенной записи FAT и родственные ФС теряют это преимущество. Отложенная запись FAT является единственным способом добиться хоть сколько-нибудь приемлемой производительности от ФС с 32-битовым FAT. Поэтому, хотя Novell NetWare и использует ФС, основанную на 32-битной FAT, после аварийной перезагрузки эта система вынуждена запускать программу аварийною становления дисковых томов. Аналогичным образом ведет себя и FAT3? Если же система хранит в одном месте список или карту свободных блоков, а в другом месте списки блоков, выделенных каждому файлу (рис. 11.17) как это делают HPFS или ФС систем семейства Unix, то при прерывании операции выделения места в неподходящий момент могут либо теряться блоки (если мы сначала удаляем блок из списка свободных— рис. 11.18) либо получаться блоки, которые одновременно считаются и свободными, и занятыми (если мы сначала выделяем блок файлу).

Первая ситуация достаточно неприятна, вторая же просто недопустима: первый же файл, созданный после перевызова системы, будет "перекрещиваться" с испорченным (рис. 11.19). Поэтому все ОС, использующие файловые системы такого типа (системы семейства Unix, OS/2, Windows NT и т. д.), после аварийной перезагрузки первым делом проверяют своп ФС соответствующей программой восстановления.

Рис. 11.17. Модификация структур данных сложной ФС

Рис. 11.18. Потерянный блок

Рис. 11.19. Пересекающиеся файлы

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



Восстановление ФС после сбоя


Восстановление ФС после сбоя

Чаще всего суперблок неустойчивых ФС содержит флаг flirty ("грязный"), сигнализирующий о том, что ФС, возможно, нуждается в восстановлении. Этот флаг сбрасывается при нормальном размонтировании ФС и устанавливается при ее монтировании или при первой модификации после монтирования. Таким образом, если ОС погибла, не успев размонтировать свои дисковые тома, после перезагрузки на этих томах dirty-флаг будет установлен, что и станет сигналом необходимости починки.

Восстановление состоит в том, что система проверяет пространство, выделенное всем файлам. При этом должны выполняться следующие требования.

1. Каждая запись в каталоге должна иметь правильный формат и содержать осмысленные данные. Например, если запись помечена как свободная, она не должна ссылаться на данные, помеченные как принадлежащие файлу, или на и под. Не во всех ФС можно обнаружить ошибки такого типа.

2. Каждый блок или кластер диска должен принадлежать не более, чем одному файлу. Блоки, принадлежащие одновременно двум или более файлам, являются очень серьезной ошибкой. На практике это означав что данные во всех этих файлах (в лучшем случае — во всех, кроме того запись в который была последней) безнадежно испорчены. Чаще всего программа восстановления в этой ситуации требует вмешательства попь зователя, с тем чтобы решить, какие из файлов следует удалить или обре зать по месту пересечения. Иногда для каждого из файлов создается ко пия "общего" блока, но и в этом случае пользователю все равно нужно определить, какие из файлов испорчены.

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

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

4. Все блоки, не принадлежащие файлам, должны быть помечены, как свободные. Соответствующий тип ошибок — потерянные блоки — наиболее частый результат системных сбоев как в файловой системе FAT, так и в более сложных файловых системах. Сами по себе ошибки этого типа относительно безобидны.

Обычно программа восстановления не помечает потерянные блоки как свободные, а выделяет из них непрерывные цепочки и создает из этих цепочек файлы. Например, в OS/2 программа восстановления пытается найти в потерянных блоках файловые записи, а потом создает ссылки на найденные таким образом файлы в каталоге \FOUND.XXX. В DOS эти файлы помещаются в корневой каталог ФС под именами FILEXXXX.CHK (вместо ХХХХ подставляется номер). Предполагается, что пользователь просматривает все такие файлы и определяет, не содержит ли какой-то из них ценной информации, например, конца насильственно укороченного файла.

В системах семейства Unix существует несколько специфических ошибок, связанных с инодами.

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

Инод, не имеющий ни одной ссылки, но и не помеченный как свободный — сирота (orphan) (рис. 11.20). Ссылка на такой и под создается в каталоге lost+foiind;

Инод с непулевым количеством ссылок из каталогов, но помеченный как свободный. Чаще всего это свидетельствует о порче самого каталога. Обычно ссылки на такой инод удаляются.

Рис. 11.20. Инод-сирота

Ручное восстановление файловой системы

В некоторых особенно тяжелых случаях программа восстановления оказывается не в состоянии справиться с происшедшей аварией и администратору системы приходится браться за дисковый редактор.

В процессе эксплуатации системы SCO Open Desktop 4.0 у автора неоднократно возникала необходимость выполнять холодную перезагрузку без нормального размонтирования файловых систем. Одна из таких перезагрузок привела к катастрофе.

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

После перезагрузки система автоматически запустила программу восстановления файловой системы fsck (File System ChecK), которая выдала радостное сообщение: DUP in inode 2. Для незнакомых с системными утилитами Unix н обходимо сказать, что DUP означает ошибку перекрещивания файлов, а инп~ 2— это инод корневого каталога ФС. Таким образом, корневая директория дискового тома объемом около 2 Гбайт оказалась испорчена. При этом пода ляющее большинство каталогов и файлов были не затронуты катаклизмом оказались недоступны. Программа восстановления не могла перенести ссылк на соответствующие иноды в каталог lost+found, так как ссылка на него такж идет из корневого каталога.

Ситуация представлялась безвыходной. Катастрофа усугублялась тем, что произошла она во время резервного копирования, а последняя "хорошая" копия была сделана неделю назад. Большую часть пользовательских данных можно было бы восстановить, но среди потерянных файлов оказался журнальный файл сервера СУБД ORACLE (сама база данных находилась в другом разделе диска). Пришлось заняться восстановлением ФС с использованием дискового редактора, мотивируя это тем, что "терять все равно уже нечего" Собственно, в восстановлении ФС участвовало два человека — автор и штатный администратор системы. Автор ни в коем случае не хочет создать у читателя впечатление, что план восстановления был разработан лично им — это был плод совместных усилий, проб и ошибок.

Редактирование системных данных "сложных" ФС с использованием простого шестнадцатеричного дискового редактора является крайне неблагодарным занятием. Есть основания утверждать, что это вообще невозможно. Во всяком случае, автору не доводилось слышать об успехе такого предприятия. К счастью, системы семейства Unix предоставляют для редактирования ФС специальную программу fsdb (File System DeBugger— отладчик файловой системы). Пользовательским интерфейсом эта программа напоминает программу DEBUG.COM, поставляемую с MS DOS; главным ее преимуществом является то, что она "знакома" с основными понятиями файловой системы. Так, например, fsdb позволяет просмотреть содержимое 10-го логического блока файла с инодом 23 456, выделить физический блок 567 345 файлу с инодом 2 или пометить инод 1245 как свободный.

Первая попытка восстановления состояла в том, что мы удалили тот инод, с которым перекрещивался корневой каталог, смонтировали том командой "безусловного" монтирования (которая позволяла монтировать поврежденные тома), создали командой mkdir каталог lost+found и вновь запустили fsck. Попытка завершилась крахом. Беда была в том, что, как оказалось, корневой каталог пересекался также и со списком свободных блоков, т. е. создание каталога, а потом его расширение командой f sck снова приводило к порче корневого каталога и задача сводилась к предыдущей.

Таким образом, нам необходимо было либо исправить вручную список свободных блоков, либо найти способ создать директорию lost+found без обращений к этому списку. Дополнительная сложность состояла в том, что с каталогом lost+found не связано фиксированного инода, а определить инод старого lost+found не представлялось возможным.

Мы решили не связываться с восстановлением списка свободных блоков. Вместо этого мы просмотрели листинг последней "правильной" резервной копии, нашли там ненужный пустой каталог и присоединили его к корневому под названием lost+found. После этого нам оставалось лишь уповать на то, что вновь создаваемые f sck-ссылки на файлы не приведут к необходимости удлинить наш lost+found. К счастью, этого не произошло: все потомки корневого каталога благополучно получили имена в lost+found. По существу, ФС пришла в пригодное для чтения состояние, оставалось лишь правильно определить имена найденных каталогов. Это также оказалось относительно несложной задачей: большая часть каталогов на томе состояла из домашних каталогов пользователей и их имена можно было восстановить на основании того, кому эти каталоги принадлежали. Для остальных каталогов имя достаточно легко определялось после сопоставления их содержимого с листингом резервной копии.

Во многих современных ОС реализованы устойчивые к сбоям файловые системы: jfs в AIX и OS/2 v4.5, Veritas в UnixWare, NTFS в Windows NT/2000/XP. Практически все такие ФС основаны на механизме, который по-английски называется intention logging (регистрация намерений).