OSDev Wiki
Advertisement

Все структуры, описывающие части файловой системы, взяты из Linux 2.4.0, i386, linux/include/linux/ext2_fs.h  (C) 1991, 1992  Linus Torvalds



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

Физическая организация файловой системы[]

Файловую систему можно представить в виде следующей структурной схемы:

  • Суперблок (Superblock)
  • Описание группы блоков (Block Group Descriptors)
  • Битовая карта блоков (Blocks Bitmap)
  • Битовая карта индексных дескрипторов (Inode Bitmap)
  • Таблица индексных дескрипторов (Inode Table)
  • Данные


Все пространство раздела диска разбивается на так называемые блоки, имеющие порядковые номера. Блоки имеют фиксированный размер и кратны размеру сектора (1024,2048,4096...). Для уменьшения количества перемещений головки жесткого диска блоки объединяют в группы блоков.

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


Суперблок[]

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

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;   /*  Количество свободных индексных дескрипторов */
__u32   s_first_data_block;    /*  Номер данного блока */
__u32   s_log_block_size;      /*  log2(размер блока)-10 */
__s32   s_log_frag_size;       /*  log2(размер фрагмента)-10 */
__u32   s_blocks_per_group;    /*  #  Кол-во блоков в группе */
__u32   s_frags_per_group;     /*  #  Кол-во фрагментов в группе */
__u32   s_inodes_per_group;    /*  #  Кол-во индексных дескрипторов в группе */
__u32   s_mtime;               /*  Время последнего монтирования в POSIX времени */
__u32   s_wtime;               /*  Время последней записи в POSIX времени */
__u16   s_mnt_count;           
__s16   s_max_mnt_count;       
__u16   s_errors;              /*  Код ошибки(см.ниже) */
__u16   s_pad;
__u32   s_lastcheck;           /*  POSIX время последней проверки */
__u32   s_checkinterval;       /*  POSIX время между принудительными проверками */
__u32   s_creator_os;          /*  ID ОС (см. ниже)  */
__u32   s_rev_level;           /*  Версия */
__u16   s_def_resuid;          /*  UserID, могущий использовать зар. блоки */
__u16   s_def_resgid;          /*  GroupID, могущий использовать зар. блоки */
__u32   s_reserved[235];       /*  Зарезервировано */
};
ID ОС
0 Linux
1 GNU HURD
2 MASIX
3 FreeBSD
4 Other/Unknown


BGD[]

BGD таблица содержит индексные дескрипторы для каждой группы блоков файловой системы и распологается сразу после суперблока. Таким образом, если указано, что размер блока составляет 1 кб, то блок с таблицей начинается в втором блоке. Блоки нумеруются с нуля, и номера блоков не соответствуют их физическому нахождению. Формат дескриптора группы блоков в виде структуры представлен ниже:

struct ext2_group_desc
{
__u32 bg_block_bitmap;        /*  Номер блока в битовой карте*/
__u32 bg_inode_bitmap;        /*  Дескриптор блока в битовой карте */
__u32 bg_inode_table;         /*  Номер блока в таблице дескрипторов */
__u16 bg_free_blocks_count;   /*  Свободно блоков */
__u16 bg_free_inodes_count;   /*  Свободно индексных дескрипторов */
__u16 bg_used_dirs_count;     /*  Количество директорий */
__u16 bg_pad;
__u32 bg_reserved[3];
};


Индексные дескрипторы[]

В первой версии файловой системы индексные дескрипторы имели фиксированный размер в 128Кб, начиная с версии 1.0 размер инода указывается в соответствующем поле суперблока. Как и блоки, каждый дескриптор имеет свой номер, отличие лишь в том, что нумерация инодов начинается с единицы. До версии Ext2 1.0 дескрипторы с 1 по 10 были зарезервированы, но начиная с версии 1.0 первый незарезервированный инод отражается с помощью поля в суперблоке. Второй инод имеет самое большое значение, так как он используется для корневого каталога.

Поиск местонахождения дескриптора[]

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

Группа блоков = (инод-1) / s_inodes_per_group

где s_inodes_per_group соответствующее поле в суперблоке (см. Суперблок).

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

Адрес = (инод-1) % s_inodes_per_group

где % - деление по модулю.

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

Блок = (Адрес * inode_size) / block_size

Чтение информации из дескриптора[]

см. Система адресации данных Структура дескриптора

struct ext2_inode {
	__u16	i_mode;		/* Тип файла и права доступа (см.ниже) */
	__u16	i_uid;		/* UserID */
	__u32	i_size;		/* Размер в байтах */
	__u32	i_atime;	/* POSIX время последнего обращения к файлу */
	__u32	i_ctime;	/* POSIX время создания */
	__u32	i_mtime;	/* POSIX время последней модификации */
	__u32	i_dtime;	/* POSIX время удаления */
	__u16	i_gid;		/* GroupID */
	__u16	i_links_count;	/* Кол-во ссылок на дескриптор */
 	__u32	i_blocks;	/* Кол-во секторов (не блоки!) */
	__u32	i_flags;	/* Флаг (см.ниже) */
	union {
		struct {
			__u32  l_i_reserved1; /* Зарезервировано */
		} linux1;
		struct {
			 __u32  h_i_translator; /* ??? */
		} hurd1;
		struct {
			__u32  m_i_reserved1; /* Зарезервировано */
		} masix1;
	 } osd1;		
	__u32	i_block[EXT2_N_BLOCKS];/* Указатели на блок */
	__u32	i_generation;	/* Версия файла (для NFS) */
	__u32	i_file_acl;	/* Доп. аттрибуты файла */
	__u32	i_dir_acl;	/* Доп. аттрибуты директории */
	__u32	i_faddr;	/* Адрес фрагмента */
	union {
		struct {
			__u8	l_i_frag;	/* Номер фрагмента */
			__u8	l_i_fsize;	/* Размер фрагмента */
			__u16	i_pad1;         /* Зарезервировано */
			__u16	l_i_uid_high;	/* 16 старших битов UserID */
			__u16	l_i_gid_high;	/* 16 старших битов GroupID */
			__u32	l_i_reserved2;  /* Зарезервировано */
		} linux2; /* LINUX */
		struct {
			__u8	h_i_frag;	/* Номер фрагмента */
			__u8	h_i_fsize;	/* Размер фрагмента */
			__u16	h_i_mode_high;  /* 16 старших битов T&P */
			__u16	h_i_uid_high;   /* 16 старших битов UserID */
			__u16	h_i_gid_high;   /* 16 старших битов GroupID */
			__u32	h_i_author;     /* UserID или автор */
		} hurd2; /* GNU HURD */
		struct {
			__u8	m_i_frag;	/* Номер фрагмента */
			__u8	m_i_fsize;      /* Размер фрагмента */
			__u16	m_pad1;         /* Зарезервировано */
			__u32	m_i_reserved2[2]; /* Зарезервировано */
		} masix2; /* MASIX */
	} osd2;				/* Специфичные значения */
};
Тип файла и права доступа[]

В верхних четырех битах (15 по 12) поля i_mode находятся описания типа файла, а в остальных  - права доступа.

Тип файла
0x1 FIFO
0x2 Символьное устройство
0x4 Директория
0x6 Блочное устройство
0x8 Регулярный файл
0xA Ссылка
0xC UNIX-cокет


Для представления прав доступа в UNIX используется 10 битное поле, маску которого можно представить как DRWERWERWE (в данном случае нужно просто "отсечь" последние два бита) , где первый бит указывает, является ли файл специальным. Первая RWE тройка указывает права пользователя на чтение, запись, и исполнение файла, вторая - на права группы пользователя, третья - права для всех остальных. К примеру, если получена последовательность битов 0111101101 , то данный файл не является директорией, его могут исполнить и читать все "пользователи" данного компьютера, но редактировать позволено только пользователю-создателю.



Система адресации данных[]

Для хранения адреса файла выделено 15 полей по 4 байта. Если файл умещается в пределах 12 блоков, то в первых 12 полях адреса перечислены номера соответствующих кластеров, иначе следующее поле используется для косвенной адресации. Возможна ситуация, когда размер файла превышает 1024+12 блоков. Тогда 14 поле используется для двойной косвенной адресации, но если вдруг файл включает в себя более 1049612 блоков, в дело вступает тройная косвенная адресация и 15 блок. Такая организация позволяет при максимальном размере блока в 4Кб оперировать файлами, размер которых превышает 2Тб. Наглядно данная схема показана на рисунке ниже:

from Wikipedia
Advertisement