WYOS - Выпуск №7
Linux VFS, Ext 2/3...
Roman I Khimov, Среда, 30 Июнь 2004, 16:20
Напиши свою ОС! #7Здравствуйте, уважаемые подписчики!
<p>Снова в пятницу рассылка Write Your Own OS, с вами Khimov Roman.<br> Мне довелось подготовить 7-й выпуск нашей рассылки. И я этому очень
рад, поскольку для меня это совершенно особое число. Надеюсь не подведу!</p>
<p>
Немного организационныхвопросов.<br>
Мы опять остаемся на время без Олега, будем работать вдвоем - я и commrade. Это не должно сказаться сильно на рассылке,
но мне важно, чтобы вы об этом знали. А мы с commrade будем стараться!
</p>
<p>
Этот выпуск мы посвятим файловым системам Ext 2/3.
</p>
Немного истории<p>
Мне показалось, что было бы логично начать рассказ с небольшого исторического экскурса.<br>
Ext 2/3 - файловые системы разработанные специально под ОС Linux. То есть вся их структура заточена под эту ОС. Некто
Линус Торвальдс (слышали, небось?
при разработке Linux первых версий поступил очень просто - в качестве
файловой системы взял готовую файловую систему Minix. Это было довольно логично, особенно если учесть то, что первые
версии Linux в общем базировались именно на Minix. К тому же ФС Minix была стабильна и действительно неплохо сделана
для своего времени.
</p>
<p>
Тем не менее, ФС Minix имела очень много ограничений. Так, максимальный объем одного раздела не мог превышать 64 мб (а что вы хотите - разработка 1987 года, тогда это был очень большой объем!).
Соответственно, размер одного файла также не мог превышать 64 мб. Под имя файла выделялось 16 (30) символов. Больше ничего хорошего в ней и не было, только что простота да стабильность.
</p>
<p>
Когда стало понятно, что с такой ФС Linux долго не протянет, стали думать что бы такое придумать в качестве файловой системы для Linux. Пока думали над ФС, придумали как их удобнее подключать! Chris Provenzano написал VFS - Virtual File System для Linux.
Что, впрочем, не помешало Линусу Торвальдсу переписать этот код перед непосредственно интеграцией в ядро Linux.
Основная идея VFS - стандартизироваь обращение ядра и приложений с разными ФС. То есть это прокладка между драйвером
самой ФС и приложениями. Таким образом для добавления новой ФС в систему достаточно написать ее драйвер и все.
</p>
<p>
В это же время появилась файловая система Extfs - Extended File System. Extfs преодолела некоторые ограничения Minix
ФС, в частности максимальный размер раздела, равно как и максимальный размер файла стал равным 2 Гб, под имя файла
выделялось 255 символов. Тем не менее Линуксоидам не хватало поддержки трех дат (timestamp) - даты последнего обращения, даты модификации индексного дескриптора (inode) и даты последней модификации файла; а также некоторых других вещей.
</p>
<p>
Вот тогда-то и появилась Ext2fs, основная на данный момент ФС под Linux. Но о ней чуть попозже, давайте поговорим о
</p>
Linux VFS<p>
Я уже упоминал, что Virtual File System - это всего лишь прокладка между реальной ФС и тем, что доступно приложению.
А так как, и это я тоже уже упоминал, Ext 2/3 разработаны специально для Linux, вполне логично будет рассмотреть эту
прокладку поподробнее.
</p>
<p>
Принцип работы VFS очень хорошо иллюстрируется этой схемой:<br>
<img src='files/images/articles/wyos/ext2-vfs.png' align='center'><br>
<font size='-2'>© Design and Implementation of the Second Extended Filesystem - Remy Card, Theodore Ts'o, Stephen Tweedy</font><br>
Я не стал переводить эту картинку, думаю, и так все ясно.
</p>
<p>
Виртуальная файловая система определяет набор функций, который дожна поддерживать любая файловая система. Этот
интерфейс - всего лишь набор операций над четырьмя типами объектов:
<UL>
<LI><b>Супер </b> (<B>Super block</b>): хранит информацию связанную со смонтированной ФС.
Предоставляется контрольным блоком файловой системы, хранящейся на диске (для дисковых ФС).
</li>
<LI><b>Индексный </b> (<B>i-node</b>): хранит информацию, относящуюся к одному файлу. Имеет соответствие в
контрольном блоке ФС на диске. Каждый дескриптор хранит мета-данные файла: владельца, группу, дату создания,
дату последнего доступа и набор указателей на блоки диска, хранящие данные файла.
</li>
<LI><B></b>: хранит информацию относящуюся к взаимодействию между открытым файлом и процессом. Этот объект существует только во время взаимодействия процесса с файлом.
</li>
<LI><b>Запись </b> (<B>Dentry</b>): связывает путь к папке с соответствующим ему файлом. Недавно использованные
записи этого типа хранятся в кэше, для ускорения трансляции имени файла в соответствующий ему индексный дескриптор.
</li>
</ul>
</p>
Linux - Unix<P>
Как известно, Linux совместим с Unix. И Linux очень многое наследует из Unix. В файловых системах это следующие
базовые принципы:
</p>
<ul>
<li>Индексные дескрипторы - inode
<p>Каждый файл представляется структурой, называемой inode (это и есть индексный дескриптор, но для простоты
далее мы будем использовать термин inode). Inode содержит в себе описание файла:
<ul>
<li>Тип </li>
<li>Права </li>
<li>Владельцы </li>
<li>Даты создания/доступа/</li>
<li></li>
<li>Указатели на блоки с </li>
</ul>
Адреса блоков с данными, занимаемых файлом, содержатся в inode этого файла. Система inode может быть
представлена следующим изображением:<br>
<img src='files/images/articles/wyos/ext2-inode.png' align='center'><br>
<font size="-2">© Design and Implementation of the Second Extended Filesystem - Remy Card, Theodore Ts'o, Stephen Tweedy</font>
</p>
</li>
<li>Папки
<p>
Папки структуризованыв иерархическое дерево. Каждая папка может содержать файлы и папки.<br>
Логически, папки - это всего лишь файлы особого вида. Папка - это файл, содержащий список записей. Каждая запись
содержит номер inode и имя файла. Если процесс использует путь (pathname), ядро выполняет поиск по папкам в поисках
соответствующего номера inode. После того, как номер inode найден, inode загружается в память и используется при
дальнейшей работе.
Схематичное представление папки:<br>
<img src='files/images/articles/wyos/ext2-dir.png' align='center'><br>
<font size="-2">© Design and Implementation of the Second Extended Filesystem - Remy Card, Theodore Ts'o, Stephen Tweedy</font>
</p>
</li>
<li>Связи
<p>
Файловые системы Unix вводят понятие <i>свя</i> (иногда говорят - <i></i>). С одним inode могут быть
ассоциированы несколько имен файлов. inode содержит поле, содержащее количество связей с файлами. Добавление
связи сводится к созданию записи в папке, где номер inode указывает на этот inode, и увеличению числа связей в
самом inode. Когда связь удаляется, ядро уменьшает счетчик связей и освобождает inode, если счетчик равен нулю.
</p>
<p>
Такой тип связей называется <i></i> и может быть использован только в пределах одной ФС. Жесткие связи
могут быть созданы только для файлов, жесткие связи для папок невозможны, иначе возможно зацикливание в дереве
папок!
</p>
<p>
Однако существует и другой вид связей - <i></i> (<i></i>) связи. Символические связи -
это не более чем файлы, содержащие имя другого файла. Если ядро сталкивается с символической связью во время
преобразования пути в inode, оно заменяет имя связи ее содержимым, то есть именем файла, на который и указывает
эта связь, и начинает поиск inode заново. Так как символическая ссылка не связана с inode, становиться
возможным создать ссылки на другие ФС. Символические связи могут указывать на любой тип файлов, даже несуществующих.
Символические ссылки очень удобны, так как они не имеют ограничений жестких ссылок, но они требуют некоторого
места на диске, занимаемого их inode и их данными, а так же несколько замедляют процесс обращения к файлу, так как
ядру приходится заново приступать к преобразованию имени файла в inode.
</p>
</li>
<li>Отображение устройств на файловую систему
<p>
В Unix-подобных операционных системах доступ к устройствам можно получить с помощью специальных файлов. Эти файлы
не занимают никакого места в ФС, они просто являются точкой доступа к драйверу устройства.
</p>
<p>
Существуют два типа специальных файлов: символьные и блочные. Первые выполняют операции ввода/вывода в символьном
режиме, в то время как вторые предполагают обмен данными блоками (грузите апельсины бочками!
, через механизмы
буфферного кэша. Когда производятся операции ввода/вывода со специальным файлом, эти операции перенаправляются
на драйвер (псевдо-) устройства. Доступ к таким файлам производится по старшему номеру, который указывает на тип
устройства и младшему номеру, который указывает непосредственнона само устройство.
</p>
</li>
</ul>
</P>
Собственно Ext 2<p>
Ну вот мы и подошли к самой ФС Ext 2.
</p>
<p>
В качестве стандартных возможностей Ext 2 называются следующие:
<ul>
<li>Поддержка стандартных типов файлов Unix: обычных файлов, папок, файлов устройств и символических связей.
</li>
<li>Поддержка больших разделов - до 4 Тб.
</li>
<li>Поддержка длинных имен файлов - до 255 символов, однако этот лимит может быть расширен до 1012 при необходимости.
</li>
<li>Ext 2 резервирует некоторое количество блоков для пользователя <tt>root</tt>. Обычно это 5% доступных блоков.
Это позволяет администратору нормально работать даже, если ФС заполнена работой процессов других пользователей.
</li>
</ul>
</p>
<p>
Существуют и "" возможности ФС Ext 2, не присущие ФС Unix:
<ul>
<li>Файловые атрибуты позволяют пользователям изменять действия ядра при работе с наборами файлов.
</li>
<li>Поддерживается семантика BSD или System V Release 4. При монтировании ФС необходимо выбрать соответствующую опцию.
</li>
<li>Возможно использование синхронных обновлений в стиле BSD.
</li>
<li>Ext2fs позволяет выбрать размер логическго блока при создании ФС, это может быть 1024, 2048 или 4096 байт.
</li>
<li>Ext2fs предоставляет механизм быстрых символичных связей. Такие связи не занимают блоков данных в ФС. Имя файла-связи
содержиться в самом inode такой связи.
</li>
<li>Ext2fs может сама следить за своим состоянием.
На самом деле это означает, что в ФС встроены механизмы,
позволяющие форсировать проверку ФС в случае необходимости.
</li>
<li>Атрибуты файлов позволяют установить "" удаление файлов. При такои удалении на место бывшего файла
записываются случайные данные. Таким образом восстановить содержимое файла становиться невозможным.
</li>
<li>Введены новые типы файлов из 4.4 BSD ФС. <i></i> (Immutable) файлы доступны только для чтения: никто не
может их удалить или перезаписать. Это может помочь защитить важные конфигурационны файлы. <i>Конкатенационны</i> (Append-only) файлы могут быть использованы для записи, но любые данные будут только добавлены и только в конец файла. Как и неизменные файлы из нельзя удалить или переименовать.
Это может быть полезно для ведения логов (logs), где файл может только увеличиваться.
</li>
</ul>
</p>
Физическая структура Ext2fs<p>
О, это просто элементарно! После разборок с inode и связями - это просто... просто! То есть очень просто.
</p>
<p>
Физическая структура Ext2fs очень схожа с ФС BSD.<br>
Файловая система состоит из групп блоков. Группы блоков - это аналог групп цилиндров в BSD FFS. Однако группа блоков
не зависит от их физического расположения.
</p>
<p>
Общая структура ФС может быть представлена такой таблицей:<br>
<TABLE border>
<TR>
<TD><BR></TD>
<td>Супер-блок (1024 <br> со смещения <tt>1024</tt>)</td>
<TD>Первая<BR>группа </TD>
<TD>Вторая<BR>группа </TD>
<TD>...<BR>...</TD>
<TD>N-ная<BR>группа </TD>
</TR>
</TABLE>
</p>
<p>
Супер-блок содержит информацию, описывающую состояние ФС. Что расскажет о нем лучше, чем живой код?
(<tt>/usr/include/linux/ext2_fs.h</tt>)
<table border=0 bgcolor="#FFFFB3">
<tr>
<td>
<pre>
struct ext2_super_block {
__u32 s_inodes_count; /* Inodes count */
__u32 s_blocks_count; /* Blocks count */
__u32 s_r_blocks_count; /* Reserved blocks count */
__u32 s_free_blocks_count; /* Free blocks count */
__u32 s_free_inodes_count; /* Free inodes count */
__u32 s_first_data_block; /* First Data Block */
__u32 s_log_block_size; /* Block size */
__s32 s_log_frag_size; /* Fragment size */
__u32 s_blocks_per_group; /* # Blocks per group */
__u32 s_frags_per_group; /* # Fragments per group */
__u32 s_inodes_per_group; /* # Inodes per group */
__u32 s_mtime; /* Mount time */
__u32 s_wtime; /* Write time */
__u16 s_mnt_count; /* Mount count */
__s16 s_max_mnt_count; /* Maximal mount count */
__u16 s_magic; /* Magic signature */
__u16 s_state; /* File system state */
__u16 s_errors; /* Behaviour when detecting errors */
__u16 s_minor_rev_level; /* minor revision level */
__u32 s_lastcheck; /* time of last check */
__u32 s_checkinterval; /* max. time between checks */
__u32 s_creator_os; /* OS */
__u32 s_rev_level; /* Revision level */
__u16 s_def_resuid; /* Default uid for reserved blocks */
__u16 s_def_resgid; /* Default gid for reserved blocks */
/*
* These fields are for EXT2_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
__u32 s_first_ino; /* First non-reserved inode */
__u16 s_inode_size; /* size of inode structure */
__u16 s_block_group_nr; /* block group # of this superblock */
__u32 s_feature_compat; /* compatible feature set */
__u32 s_feature_incompat; /* incompatible feature set */
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
__u8 s_uuid[16]; /* 128-bit uuid for volume */
char s_volume_name[16]; /* volume name */
char s_last_mounted[64]; /* directory where last mounted */
__u32 s_algorithm_usage_bitmap; /* For compression */
/*
* Performance hints. Directory preallocation should only
* happen if the EXT2_COMPAT_PREALLOC flag is on.
*/
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
__u16 s_padding1;
__u32 s_reserved[204]; /* Padding to the end of the block */
};
</pre>
</tr>
</table>
</p>
<p>
Рекомендую привыкать. Ведь у вас английский второй родной, не так ли? Или первый?
<br>
Зато сразу все понятно. Хотя рассылка у нас на русском... Очевидное противоречие, что мне с ним делать? Я не знаю.<br>
Впрочем совесть меня все-таки заела, поэтому ниже вы и видите перед собой перевод, надеюсь достаточно адекватный.
<br>
Я подумал, что лучше будет переписать структуру заново - она довольно объемна, но это позволит избежать горизонтальной прокрутки.<br>
<table border=0 bgcolor="#FFFFB3">
<tr>
<td>
<pre>
struct ext2_super_block {
__u32 s_inodes_count;
// Количество индексных дескрипторов
__u32 s_blocks_count;
// Количество блоков
__u32 s_r_blocks_count;
// Количество зарезервированнх блоков
__u32 s_free_blocks_count;
// Количество свободных блоков
__u32 s_free_inodes_count;
// Количество свободных inode
__u32 s_first_data_block;
// Адрес первого блока с данными
__u32 s_log_block_size;
// Размер блока
__s32 s_log_frag_size;
// Размер фрагмента
__u32 s_blocks_per_group;
// Количество блоков в группе
__u32 s_frags_per_group;
// Количество фрагментов в группе
__u32 s_inodes_per_group;
// Количество inode на группу блоков
__u32 s_mtime;
// Время последнего монтирования
__u32 s_wtime;
// Время последней записи
__u16 s_mnt_count;
// Количество монтирований
__s16 s_max_mnt_count;
// Максимальное количество монтирований
__u16 s_magic;
// "Магическая" подпись
__u16 s_state;
// Код состояния ФС
__u16 s_errors;
// Код, определяет поведение ФС при обнаружении ошибок
__u16 s_minor_rev_level;
// Младший номер ревизии
__u32 s_lastcheck;
// Время последней проверки
__u32 s_checkinterval;
// Максимальное время между двумя проверками
__u32 s_creator_os;
// ОС, создавшая раздел
__u32 s_rev_level;
// Уровень ревизии
__u16 s_def_resuid;
// Стандартный ID пользователя для резервированныхблоков
__u16 s_def_resgid;
// Стандартный ID группы для резервированныхблоков
//
// Следующие далее поля только для супер-блоков EXT2_DYNAMIC_REV версии Ext 2
//
// Примечание: разница между совместимым набором функций и несовместимым
// в том, что если в несовместимых функциях встретиться незнакомый ядру
// набор бит, то оно откажется монтировать ФС.
//
// Требования программы проверки ФС e2fsck более строгие. Если она не знает
// о функции в совместимом или несовместимом наборе функций, она должна
// прервать свое выполнение и не пытаться связываться с вещями, которых она
// не понимает...
//
__u32 s_first_ino;
// Первый нерезервированнй inode
__u16 s_inode_size;
// Размер структуры inode
__u16 s_block_group_nr;
// Количество групп блоков для этого супер-блока (для всей ФС?)
__u32 s_feature_compat;
// Набор совместимых функций
__u32 s_feature_incompat;
// Набор несовместимых функций
__u32 s_feature_ro_compat;
// Набор совместимых функций только для чтения
__u8 s_uuid[16];
// 128-битный уникальный ID раздела
char s_volume_name[16];
// Метка (имя) раздела
char s_last_mounted[64];
// Папка, в которую в последний раз монтировалась ФС
__u32 s_algorithm_usage_bitmap;
// Для функций компрессии
//
// Оптимизационные"". Кэширование путей папок будет происходить
// только если установлен флаг EXT2_COMPAT_PREALLOC.
//
__u8 s_prealloc_blocks;
// Количество блоков, которые можно пытаться кэшировать
__u8 s_prealloc_dir_blocks;
// Количество кэшируемых папок
__u16 s_padding1;
__u32 s_reserved[204];
// Заполнение окончания блока
};
</pre>
</td>
</tr>
</table>
</p>
<p>
Каждая группа блоков содержит дополнительную копию критической контрольной информации ФС (суперблоки и дескрипторы ФС)
и содержит часть самой ФС (карта блоков, карта inode, кусок таблицы inode и блоки данных).
</p>
<p>
Структура группы блоков представляется такой таблицей:<br>
<TABLE border>
<TR>
<TD><BR></TD>
<TD><BR></TD>
<TD><BR></TD>
<TD><BR>inode</TD>
<TD><BR>inode</TD>
<TD><BR></TD>
</TR>
</TABLE><br>
Или живым кодом (<tt>/usr/include/linux/ext2_fs.h</tt>):<br>
<table border=0 bgcolor="#FFFFB3">
<tr>
<td>
<pre>
struct ext2_group_desc
{
__u32 bg_block_bitmap; /* Blocks bitmap block */
__u32 bg_inode_bitmap; /* Inodes bitmap block */
__u32 bg_inode_table; /* Inodes table block */
__u16 bg_free_blocks_count; /* Free blocks count */
__u16 bg_free_inodes_count; /* Free inodes count */
__u16 bg_used_dirs_count; /* Directories count */
__u16 bg_pad;
__u32 bg_reserved[3];
};
</pre>
</td>
</tr>
</table><br>
Неужели и тут нужен переводчик?
Не обижайтесь, но ИМХО тут все очень просто.
</p>
<p>
Использование групп блоков - большой плюс в надежности ФС: каждая группа блоков хранит копию контрольных структур. При
необходимости очень легко можно восстановить супер-блок. Такая структура также позволяет достичь большей производительноти ФС, так как сокращается расстояние от таблицы inode до непосредственноданных, а значит винчестер
будет немного меньше шуршать головками, а это - самая "тормозная" операция во всем цикле чтения.
</p>
<p>
В файловой системе Ext2 папки представляются как связанные списки с записями переменной длины. Каждая запись
содержит номер inode, длину записи, имя файла и длину этого имени. Выглядит это все где-то так:<br>
<TABLE border>
<TR>
<TD>Номер inode</TD><TD>Длина </TD>
<TD>Длина имени </TD><TD>Имя </TD>
</TR>
</TABLE>
</p>
<p>
Пример использования такой структуры, папка с тремя файлами (<TT>file1</TT>,
<TT>long_file_name</TT> и <TT>f2</TT>):<br>
<TABLE border>
<TR><TD>i1</TD><TD>16</TD><TD>05</TD><TD><TT>file1 </TT></TD></TR>
</TABLE>
<TABLE border>
<TR><TD>i2</TD><TD>40</TD><TD>14</TD><TD><TT>long_file_name </TT></TD></TR>
</TABLE>
<TABLE border>
<TR><TD>i3</TD><TD>12</TD><TD>02</TD><TD><TT>f2 </TT></TD></TR>
</TABLE>
</p>
<p>
Сами inode, которые вам так надоели (а может понравились?
за этот выпуск определены в <tt>/usr/include/linux/ext2_fs.h</tt> так:<br>
<table border=0 bgcolor="#FFFFB3">
<tr>
<td>
<pre>
struct ext2_inode {
__u16 i_mode; /* File mode */
__u16 i_uid; /* Low 16 bits of Owner Uid */
__u32 i_size; /* Size in bytes */
__u32 i_atime; /* Access time */
__u32 i_ctime; /* Creation time */
__u32 i_mtime; /* Modification time */
__u32 i_dtime; /* Deletion Time */
__u16 i_gid; /* Low 16 bits of Group Id */
__u16 i_links_count; /* Links count */
__u32 i_blocks; /* Blocks count */
__u32 i_flags; /* File flags */
union {
struct {
__u32 l_i_reserved1;
} linux1;
struct {
__u32 h_i_translator;
} hurd1;
struct {
__u32 m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
__u32 i_dir_acl; /* Directory ACL */
__u32 i_faddr; /* Fragment address */
union {
struct {
__u8 l_i_frag; /* Fragment number */
__u8 l_i_fsize; /* Fragment size */
__u16 i_pad1;
__u16 l_i_uid_high; /* these 2 fields */
__u16 l_i_gid_high; /* were reserved2[0] */
__u32 l_i_reserved2;
} linux2;
struct {
__u8 h_i_frag; /* Fragment number */
__u8 h_i_fsize; /* Fragment size */
__u16 h_i_mode_high;
__u16 h_i_uid_high;
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
struct {
__u8 m_i_frag; /* Fragment number */
__u8 m_i_fsize; /* Fragment size */
__u16 m_pad1;
__u32 m_i_reserved2[2];
} masix2;
} osd2; /* OS dependent 2 */
};
</pre>
</td>
</tr>
</table><br>
Ох, чувствую, выпрут меня с поста редактора за чрезмерное давление на мозг подписчиков исходными кодами...
</p>
<p>
Вот и вся физическая суть. Неужели, спросите вы? Да, действительно, не совсем вся, но - основная! А вот если вы не
поленитесь пройтись до <tt>/usr/include/linux/ext2_fs.h</tt>, то сможете узнать еще кое-что. Мелочи, в основном...<br>
Что говорите, Linux'а нету? Зря. Поставьте. Попробуйте. Это такой конструктор "умелые ", если вы наш подписчик, то
вам должно это понравиться...
</p>
Журналируемые ФС<p>
Ну не зря же выпуски выходят по пятницам! Выходные уже вот-вот или уже... Отдохните, попейте чайку... А потом
приступайте к дальнейшему чтению. Тут совсем немного осталось.
</p>
<p>
С журналируемыми ФС вы уже немного знакомы, хотя бы на примере NTFS, о которой нам так замечательно поведал в
предыдущем выпуске commrade. Только там говорилось о <i>транзакция</i>, но суть от этого не меняется.
</p>
<p>
В чем принципиальное преимущество журналируемых ФС? В том, что все операции записываются в лог (журнал). Вспомните,
как Win 95-98 просила вас о проверке диска после очередного выпадения в осадок с жестким reset'ом. И часто вы с ней
соглашались?
А ведь на кону ваши данные! Может конечно это ничто - save файлы любимых игр, пара картинок да
десяток музыкальных файлов... А мне, например, растерять свою 42-гигабайтную коллекцию музыки было бы очень обидно!
А еще документы разные, архивы... Я имел честь однажды (в этом году) потерять после сбоя всю почтовую базу, она
тогда лежала на FAT32, с хитрым пояснением - "зато я всегда получу к ней доступ. FAT читается ". И что? Ушла
база на тот свет и все... Читай - зачитаешься... Вот тогда-то меня и посетила мысль о чем-то более надежном. Собственно, я отвлекся. Вернемся к журналам.
</p>
<p>
Что дает этот самый журнал. Он дает одну простую вещь - если произошел сбой, то мы всегда можем определить в каком
месте он произошел и что <u></u> мы потеряли, недописали, недочитали. А значит процесс восстановления после сбоя
фактически не нужен! Для полной проверки FAT, равно как и Ext2fs нужно большое количество времени (у вас же ведь не
на 1 Гб винчестер?
, а имея журнал - мы ничего проверять не будем! Будем знать, что вот это мы так и не успели
дописать, очень жаль, реже надо на reset жать, но более ничего не затронуто! Более того, мы сможем восстановить наши
данные, даже в случае перезаписи, так как в журнал пишется вся активность. Да, это, возможно, будет не последний save,
но это будет что-то, всяко лучше чем полная потеря файла! Или, что очень актуально для FAT - потеря еще кучи других
файлов...
</p>
<p>
Надеюсь мне удалось вас убедить в правильности журналируемых ФС?
</p>
Ext3fs<p>
Ext 3 - это, к моему сожалению (не подумайте, что это действительно трагично, но мне, почему-то, немного обидно...),
всего лишь расширение ФС Ext 2, о которой вы теперь так много знаете. Ext 3 имеет точно такую же стуктуру, как и Ext 2,
но Ext 3 ведет журнал, а Ext 2 - нет. Это не позволяет раскрыть весь потенциал журналируемых ФС (в этом плане стоит
обратить внимание на ReiserFS и XFS), но зато позволяет монтировать разделы Ext 3 как Ext 2 и получать свободный
доступ к данным.
</p>
<p>
Ext 3 резервирует один из специальных inode'ов для ведения рабочего журнала, но это может быть любой inode на любой
ФС, в любой группе блоков. То есть возможно ведение одного журнала для нескольких ФС.
</p>
<p>
Задача журнала - запись нового содержимого блоков метаданных ФС во время процесса фиксации транзакций. Еще одним
дополнением является то, что система должна элементарно гарантировать фиксацию транзакций.
</p>
<p>
В журнал записывается три типа блоков данных:
<ul>
<li></li>
<li>Блоки </li>
<li>Заголовочные </li>
</ul>
</p>
<p>
Блок метаданных журнала содержит полностью один блок метаданных ФС, такой, как он обновляется транзакцией. Даже при
малейших изменениях в ФС необходимо записать полный журнальный блок. Тем не менее, это не очень сильно сказывается
на производительноти, так как эти операции специально оптимизируются.
</p>
<p>
Блоки дескрипторов описывают другие блоки метаданных журнала, так что механизм восстановления данных может скопировать
метаданные назад в основную ФС. Эти блоки записываются перед любыми изменениями метаданных журнала.
</p>
<p>
И, наконец, заголовочные блоки описывают заголовки и окончания журнала плюс порядковый номер, для гарантии порядка
записи во время восстановления.
</p>
<p>
Кстати, если вы не забыли домашнее задание... Что уже не помните? А прогуляться до <tt>/usr/include/linux/ext2_fs.h</tt>? Вот. То-то же. Так вот, прогуляйтесь заодно и до <tt>/usr/include/linux/ext3_fs.h</tt>, это недалеко...
</p>
Наш выбор <p>
Итак, это фактически окончание этого выпуска. Я постарался познакомить вас с файловыми системами Ext 2/3 и, надеюсь,
мне это удалось.
</p>
<p>
Вам, может быть, интересно, а какие ФС использую я, так долго распинавшийся про возможности Extended файловых систем?
Ну что же, у меня один раздел с NTFS, где обитает Windows XP, далее Linux Swap, далее раздел Ext (барабанная дробь!
<b>3</b>, после чего еще один большооой раздел NTFS. Изначально я очень хотел, чтобы в конце тоже был Ext 3, но
проблемы с подключением таких разделов под Windows меня заели и... Я подумал, что NTFS <i></i> современные
пингвины любых пород умеют. А это уже хорошо. А вам порекомендую тоже выбирать себе ФС из этих двух - NTFS и Ext 3, вы
же заботитетсь о сохранности ваших данных? Вот и я о том же... Лучше чуууть-чуть пожертвовать скоростью, но иметь
гораздо большую надежность.
</p>
Будущее ФС<p>
Этот выпуск завершает тему файловых систем, поэтому я подумал, что было бы неплохо рассказать и о более новых ФС.
</p>
<p>
Я уже упоминал <a href='http://oss.sgi.com/projects/xfs/'>XFS</a> - появилась она 1 мая 2001 года. И видимо первая ее буква "" все-таки означает "хорошая"!
Во внутренней структуре используются так называемые <b>B+tree</b>, то есть балансированныедеревья. Это ускоряет
работу ФС, особенно при большом количестве файлов. Используются очень интересные техники резервирования пространства,
все не охватить - это же уже бонус к выпуску! XFS позволяет использовать блоки различной длины - от 512 байт
до 64 килобайт. Еще одна интереснейшая возможность XFS - <i></i> логирование деятельности. Конечно
соблюдается тот принцип, что любые данные сначала проходят через журнал. Однако это дает следующие преимущества:
<ul>
<li>Несколько одновременных обновлений могут быть описаны в одной записи.
</li>
<li>Скорость обновления метаданных становится малозависящей от скорости самих дисков. Эта независимость, конечно,
ограничена буферизацией выделенной под ведение журнала, но это намного лучше, чем синхронные обновления старых ФС.
</li>
</ul>
</p>
<p>
<a href='http://www.namesys.com/'>ReiserFS</a>, как бы он ни был хорош, мне не очень понравился тем, что поддерживает журналирование только метаданных,
поэтому не может гарантировать сохранность данных в полной мере.
</p>
<p>
<a href='http://ban.joh.cam.ac.uk/~adm36/StegFS/'>Steganographic File System</a> - файловая система для параноиков вроде меня... Шифруется все и везде. Это в общем-то
это единственное, на что можно обратить внимание в этой ФС, но это - и есть самая ее изюминка!
</p>
<p>
Есть еще одна интересная ФС - <a href='http://www.complang.tuwien.ac.at/czezatke/lfs.html'>LinLogFS</a>, ранее
известная как dtfs. Эта ФС построена по очень интересному принципу - все данные пишутся последовательнов конец диска,
то есть как лог файл - только добавления и только в конец. Это очень удобно для сохранности данных, ведение журнала
при таком подходе совершенно необязательно - недописанные данные и так будут видны, а старая копия (а то и несколько
копий!) есть в логе. При удалении достаточно пометить запись как свободную, а при нехватке места просто переместить
все записи выше этой на ее уровень. Такой подход также позволяет свободно делать backup'ы при одновременной работе
с ФС - в бэкап пойдут старые записи лога, а новые никому мешать не будут. Изменение размера раздела становиться
очень простой задачей - ведь лог начинают писать от начала раздела, а значит достаточно уменьшить/увеличить количество
доступных блоков и все. Никаких лишних перемещений данных.
</p>
<p>
Но всего не охватишь. Яндекс в помощь! И вы найдете еще много интересного по этой теме...
</p>
Заключение<P>
Следующий выпуск будет посвящен техникам управления памятью, выпускающий - commrade.
</p>
<p>
У меня все. Вопросы по этому выпуску лучше сразу направляйте в OS-development, обсудим все вместе. Ну а если после
такого выпуска у вас возникли сомнения в психическом здоровье автора - милости просим на <a href='mailto:khimov@osrc.info'>khimov@osrc.info</a>
</p>
И все-таки мне кажется, что файловые системы должны помереть... За базами данных - будущее! Даже Microsoft до этого
додумалась... А вы как считаете? Жду на форуме!
</p>
это контент от Центр информации по операционным системам
( http://www.osrc.info/plugins/content/content.php?content.11 )