Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Kernels
 Boot 
 Memory 
 File system
 0.01
 1.0 
 2.0 
 2.4 
 2.6 
 3.x 
 4.x 
 5.x 
 6.x 
 Интервью 
 Kernel
 HOW-TO 1
 Ptrace
 Kernel-Rebuild-HOWTO
 Runlevel
 Linux daemons
 FAQ
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 Secure Programming for Li...6507 
 Linux Kernel 2.6...5279 
 Trees...1118 
 Максвелл 3...1050 
 William Gropp...987 
 Go Web ...961 
 Ethreal 3...929 
 Ethreal 4...915 
 Gary V.Vaughan-> Libtool...913 
 Ext4 FS...901 
 Clickhouse...900 
 Rodriguez 6...899 
 Ethreal 1...896 
 Steve Pate 1...884 
 C++ Patterns 3...860 
 Assembler...853 
 Ulrich Drepper...844 
 DevFS...786 
 MySQL & PosgreSQL...771 
 Стивенс 9...757 
 
  01.01.2024 : 3621733 посещений 

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 можно также на отмонтированном устройстве добавлять/удалять каталоги и файлы, т.е. работать как с полноценной партицией, после чего можно устройство в любой момент примонтировать обратно.

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

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

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