Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org

1. Minix File System

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

Мы рассматриваем линуксовую реализацию файловой системы миникс, которая конечно в чем-то отличается от нативной. В ядре линукса в ее исходниках присутствуют следы первой, второй и третьей версий. Причем в разных ветках линуксового ядра - если сравнивать 2.6.x и 3.x.x - существуют различия в реализациях линуксового модуля файловой системы миникс, что связано не с самой файловой ситемой, а с реализацией VFS - виртуальной файловой системы - в самом линуксовом ядре. Заголовок minix_fs.h в линуксовом ядре не изменился и практически полностью совпадает как в версии 2.6.32, так и в 3.4.11 .
Также, если брать основные параметры - такие как размер ноды - то они одинаковы как в линуксовой, так и в нативной версиях - и там, и там размер ноды сначала равнялся 32 байтам, а позже стал равен 64 байтам.

Рассмотрим подробнее, как устроена фаловая система minix.

В начале диска первым блоком в любой файловой системе всегда идет загрузочный сектор размером в 512 байт. Дальше идет суперблок, в котором записана основная информация - размер блока, число нод и т.д. С помощью этих параметров, записываемых на диске, позже вычисляются размеры битовых карт и другие параметры. Например, при размере блока в 1 килобайт (это один из ранних стандартов для файловой системы миникса) размер битмапа - или битовой нодоовой карты - или просто таблицы битов, которая является хранилищем индексов нод - равен одному килобайту - или 8 килобитам - т.е. хранит информацию о 8192 нодах. Если например в файловой системе 10000 нод, то ей с избытком хватает всего двух блоков для размещения битмапа этих нод (на каждую ноду - по одному биту). Сама нода в миниксе имеет размер в 64 байта - это еще один стандарт миникса. Соответственно в одном блоке может храниться 16 нод:
64 * 16 = 1024

Суперблок миникса при записи на диск хранит следующие параметры:

  число нод
  число блоков, отведенных под битовую карту нод - node bit map 
  число блоков, отведенных под битовую карту блоков - block bit map 
  начальный адрес, с которого хранятся сами файлы
  двоичный логарифм отношения block/zone
  максимально возможный размер файла
  магическое число
  число блоков
 
  
 struct minix_super_block {
   __u16 s_ninodes;   /* число нод */
   __u16 s_nzones;    /* число зон */
   __u16 s_imap_blocks;  /* число блоков */
   __u16 s_zmap_blocks;	/* число блоков  */
   __u16 s_firstdatazone;	/* начало блоков с данными */	
   __u16 s_log_zone_size;	/* размер зоны с данными */
   __u32 s_max_size;	/* максимальный размер файла */
   __u16 s_magic;	/**/
   __u16 s_state;	/**/
   __u32 s_zones;	/**/
 }; 
 
После того, как суперблок считывается с диска в память, на основании этих параметров будут вычислены другие, которые на диске не хранятся:
  указатель на рутовую ноду
  адрес первого свободного бита в карте нод
  адрес первого свободного бита в карте блоков
  устанавливается флаг на чтение/запись для всей файловой системы
  и т.д. 
  

В миниксе блоки могут быть обьединены в зоны по 2, 4, 8, ... и т.д. блоков. Зона также может быть равна одному блоку.

Битмап блоков ссылается только на блоки данных. В обоих битовых картах первый и второй биты не используются и соответственно равны 0 и 1.

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

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

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

Адрес блока на диске имеет размер в 32 бита. Блок имеет размер в 1 килобайт. можно посчитать, сколько адресов блоков можно сохранить в одном блоке:

1024 : 4 = 256

Т.е. один косвенный указатель может указывать еще на 256 блоков. А вот косвенный указатель второго уровня может указывать:

256 * 256 = 65536

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

В заголовке minix_fs.h есть две версии ноды - первая и вторая: Первая - 32-байтная, вторая - 64-байтная. Во второй присутствует дополнительный косвенный указатель третьего уровня на блоки данных, что позволяет снять ограничение на максимальный размер в 64 мегабайта:

 struct minix_inode {
   __u16 i_mode;
   __u16 i_uid;
   __u32 i_size;
   __u32 i_time;
   __u8  i_gid;
   __u8  i_nlinks;
   __u16 i_zone[9];
 };
 
 struct minix2_inode {
   __u16 i_mode;
   __u16 i_nlinks;
   __u16 i_uid;
   __u16 i_gid;
   __u32 i_size;
   __u32 i_atime;
   __u32 i_mtime;
   __u32 i_ctime;
   __u32 i_zone[10];
 }; 
 
При использования косвенного указателя третьего уровня максимально возможный размер файла:

7K + 256K + 256 * 256K + 256 * 256 * 256K = 16 гигабайт

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

Директории в том же заголовке также имеют две версии - отличие только в разрядности поля inode:

 struct minix_dir_entry {
   __u16 inode;
   char name[0];
 };
 
 struct minix3_dir_entry {
   __u32 inode;
   char name[0];
 };
 
В первом случае получаем, что для 2-байтной inode максимально возможное количество файлов во всей файловой системе равно
2^16 = 65536

Во втором случае:
2^32 = 4294967295

2. mkfs.minix

Теперь нам нужна утилита для создания партиции, куда мы положим файловую систему minix. Эта утилита лежит в пакете util-linux.

Размер блока - MINIX_BLOCK_SIZE - ограничен и равен одному килобайту.

Как работает эта утилита ? В ее заголовке (mkfs.minix.c) по умолчанию прописана первая версия файловой системы:

int fs_version = 1;

Номер версии можно задать из командной строки с помощью параметра v:

mkfs.minix -v3 /dev/sda

В зависимости от версии утилита ведет себя по-разному. Я использовал для экспериментов чистую партицию размером в 15 гигов. Для первой версии утилита после ее форматирования выдает следующий результат:

 21856 inodes
 65535 blocks
 Первая зона данных=696 (696)
 Размер зоны=1024
 Макс. размер=268966912
 
Для второй версии
 65535 inodes
 15358108 blocks
 Первая зона данных=2358 (2358)
 Размер зоны=1024
 Макс. размер=2147483647
 
Для третьей версии
 5119376 inodes
 15358108 blocks
 Первая зона данных=60280 (322424)
 Размер зоны=1024
 Макс. размер=2147483647
 
Для первой и второй версий длина имени файла и длина директории равны соответственно 30 и 32 байтам, для третьей - 60 и 64 байта.

Утилита mkfs.minix последовательно записывает на устройство сначала загрузочные 512 байт, затем суперблок размером в один килобайт, затем две битовых таблицы, затем таблицу нод.

 static void
 write_tables(void) {
 	/* Mark the super block valid. */
 	Super.s_state |= MINIX_VALID_FS;
 	Super.s_state &= ~MINIX_ERROR_FS;
 
 	if (lseek(DEV, 0, SEEK_SET))
 		die(_("seek to boot block failed in write_tables"));
 	if (512 != write(DEV, boot_block_buffer, 512))
 		die(_("unable to clear boot sector"));
 	if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET))
 		die(_("seek failed in write_tables"));
 	if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE))
 		die(_("unable to write super-block"));
 	if (IMAPS*BLOCK_SIZE != write(DEV,inode_map,IMAPS*BLOCK_SIZE))
 		die(_("unable to write inode map"));
 	if (ZMAPS*BLOCK_SIZE != write(DEV,zone_map,ZMAPS*BLOCK_SIZE))
 		die(_("unable to write zone map"));
 	if (INODE_BUFFER_SIZE != write(DEV,inode_buffer,INODE_BUFFER_SIZE))
 		die(_("unable to write inodes"));
 	
 }
 
Для работы с файловой системой minix нужно включить ее поддержку в ядре:

modprobe minix

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

mount -t minix /dev/sda /mnt/sda

3. mfstools

mfstools - Minix File System Tools - пакет для работы с файловой системой миникс в обычном пользовательском режиме. С помощью этой утилиты можно отформатировать устройство, получить статистику, добавить-удалить в устройство файл или директорию. Она может генерировать загрузочный образ для использования в устройствах при инициализации.
Ее можно найти тут

Сгенерируем образ файловой системы в виде обычного регулярного файла и дадим ему название image_test:

dd if=/dev/zero of=image_test count=200k

Размер файла при этом 100 метров. Генерируем файловую систему minix на этом образе:

./mfstool mkfs image_test -s 100000

Дальше можно примонтировать отформатированный образ стандартным образом:

mount -t minix -o loop=/dev/loop0 image_test /mnt/test

После чего можно работать с примонтированной партицией как с нативной(при условии, что мы выполнили команду modprobe minix) - добавлять туда каталоги и файлы. Потом можно отмонтировать устройство:

umount /mnt/test

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

./mfstool dir image_test /

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

Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье