"Сложные" файловые системы
Еще одно любопытное следствие применения стратегии 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);
Рис. 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; /* Этот инод только что вьделен */