Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Обучение от Mail.Ru Group.
Онлайн-университет
для программистов с
гарантией трудоустройства.
Набор открыт!
2009 г.

Записки исследователя NTFS

Artem Baranov

Содержание

Общие сведения
Общие концепции NTFS
Таблица MFT
Атрибуты
Каталоги
Распространенные атрибуты
Ссылки

Общие сведения

NTFS (NT File System) – файловая система, которая разрабатывалась Microsoft специально для Windows NT. Написание NTFS шло параллельно с разработкой самой этой ОС. Известно, что NT зарождалась не в вакууме; в ее основу были положены идеи серверной системы VMS «high-end» класса компании DEC (в 1998 она была куплена Compaq, которая затем была поглощена Hewlett-Packard). ОС VMS работала на железе DEC, включая 32-битные компьютеры VAX и 64-битные машины на основе процессора Alpha. Каким-то образом команда, работавшая над созданием VMS, перекочевала в Microsoft для создания NT. Во главе этой команды находился Дэйв Катлер (Dave Cutler), крестный отец NT, разработчик ядра системы. Основная версия причины перехода Катлера в Microsoft – закрытие проекта разработки нового RISC-процессора и соответствующей ОС, в котором он работал вместе со своей командой инженеров. В результате, не без участия Билла Гейтса, Дэйв со своей командой оказался в Microsoft. Кстати, Гейтс был очень заинтересован в создании новой ОС, потому что у Microsoft на тот момент была только Windows, пригодная для домашних пользователей, а выхода на рынок серверов не было.

Архитекторами NTFS были Том Миллер (Tom Miller) и Гэри Кимура (Gary Kimura), которые работали программистами в команде Катлера в DEC. Так же, как NT влила в себя идеи VMS, NTFS основывалась на идеях файловой системы VMS – Files-11, в которой, в частности, поддерживались списки контроля доступом (ACL), а также ввод/вывод, ориентированный на записи (record-oriented I/O) [1] [2].

NTFS разрабатывалась, прежде всего, как ФС для ОС корпоративного уровня, какой и являлась NT. Предыдущие файловые системы FAT и HPFS (ФС для OS/2) были способны удовлетворить потребностям рядовых пользователей, но не имели достаточных возможностей для корпоративной среды, таких как защищенность файлов, отказоустойчивость и восстанавливаемость. В связи с этим Microsoft выработала следующие требования к новой ФС класса «high end». (Эти требования были перечислены у Хелен Кастер в «Основах Windows NT и NTFS», первой книге, которая проливала свет на внутреннее устройство NT).

  • Восстанавливаемость. В случае сбоя диска, NTFS должна привести себя в рабочее, целостное состояние. В лучшем случае, NTFS вернется в состояние, которое непосредственно предшествовало сбою, в худшем какая-то пользовательская информация может быть потеряна, но том останется в рабочем состоянии. Восстанавливаемость реализуется через модель обработки транзакций. Транзакция не что иное, как операция I/O, которая изменяет структуры NTFS. Если такая операция не завершается полностью, то NTFS откатывает свои структуры данных до состояния перед выполнением транзакции.
  • Защита от несанкционированного доступа. Файлы и каталоги NTFS обладают дескрипторами защиты, что позволяет контролировать доступ к ним в рамках общей модели безопасности NT. Подобными дескрипторами защиты обладают все объекты NT (процессы, потоки, разделы и пр.).
  • Отказоустойчивость. Если восстанавливаемость гарантирует целостность тома после сбоя, то отказоустойчивость может гарантировать восстановление пользовательских данных. Это реализуется за счет избыточности данных и RAID. Дублирование данных осуществляется на уровне диспетчера томов, который копирует записываемые данные на другом диске.
  • Диски и файлы большого объема. В NTFS реализуется очень эффективная поддержка больших дисков и файлов. Для хранения номера кластера используется 64 бита или 8 байт. Т. о. NTFS позволяет адресовывать 2^64 кластеров, при стандартном размере кластера в 4KB и максимальном 64KB. Под размер файлов также выделено 8 байт, что позволяет адресовывать очень большие файлы.
  • Поддержка POSIX. Также как NT, NTFS полностью соответствует стандарту POSIX 1003.1. Главная особенность формата заключается в назначении имен файлам с учетом регистра символов, а также реализация жестких связей (hard links). Жесткие связи позволяют файлам из разных каталогов ссылаться на одни и те же данные. Жесткая связь создается для существующего файла и указывает на его данные, хотя для пользователя такой объект выглядит как файл.

Разработка новой файловой системы, которая должна удовлетворять вышеперечисленным требованиям очень сложный процесс и здесь разработчики учли опыт MS в разработке FAT и HPFS. Том Миллер так описывает процесс разработки новой ФС:

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

NTFS имеет следующие версии.

  • Версия 1.0. Была выпущена вместе с NT 3.1 в середине 1993. Включает самый основной функционал ФС.
  • Версия 1.1. Была выпущена вместе с NT 3.5 в 1994.
  • Версия 1.2. Была написана для NT 3.51 (середина 1995) и для NT 4 (середина 1996); последняя, также известна как «NTFS 4.0». Добавлена поддержка сжатия файлов, именованных потоков, защита файлов на основе списков ACL.
  • Версия 3.0. Поставляется с Windows 2000 (известна как «NTFS V5.0»). Добавлена поддержка дисковых квот, шифрования, разреженных файлов (sparse files), точек повторного разбора (reparse points), служебный метакаталог $Extend и его файлы
  • Версия 3.1. Поставляется с Windows XP (осень 2001, «NTFS V5.1»), Windows 2003 (весна 2003, «NTFS V5.2»), Windows Vista (середина 2005, «NTFS V6.0»).

Общие концепции NTFS

  • Метафайлы NTFS – служебные файлы, используемые NTFS для поддержания своей внутренней структуры.
  • Том (volume) NTFS – раздел, отформатированный под NTFS.
  • Главная загрузочная запись (Master Boot Record) – первый сектор жесткого диска, который содержит загрузочный код (bootstrap code) и таблицу разделов (partition table). Загрузочный код читает таблицу разделов, ищет активный (флаг 0x80) раздел и передает управление на его первый сектор (загрузочный сектор).
  • Загрузочный сектор (boot sector) – первый сектор тома, в котором хранятся параметры ФС. Также в загрузочный сектор входит код, который отвечает за чтение ntldr в память. Такой код несет смысл только если том является системным (т. е. только для диска C). В процессе монтирования тома, ntfs.sys проводит валидацию загрузочного сектора и признает его своим в случае совпадение необходимых параметров.
  • Системный том (system volume) – том, на котором располагается ntldr. Для NT системным томом может быть только первый том – С:. Загрузочный том (boot volume) – том, на котором располагается папка windows (winnt).

Формат загрузочного сектора NTFS описывается следующей таблицей (как и все остальные описываемые структуры, наилучшим руководством по ним может служить книга Брайана Кэрриэ «Криминалистический анализ файловых систем»).
Смещение Размер в байтах Описание
0x0 3 Команда перехода на загрузочный код.
0x3 8 Сигнатура ‘NTFS    ’.
0xB 2 Количество байт на сектор
0xD 1 Количество секторов в кластере.
0xE 2 Должно равняться нулю.
0x10 1 Должно равняться нулю.
0x11 2 Должно равняться нулю.
0x13 2 Должно равняться нулю.
0x15 1 Тип носителя
0x16 2 Должно равняться нулю.
0x18 2 Должно равняться нулю.
0x1A 2 Должно равняться нулю.
0x1C 4 Не используется.
0x20 4 Должно равняться нулю.
0x24 4 Не используется.
0x28 8 Число секторов в томе.
0x30 8 Стартовый кластер MFT.
0x38 8 Стартовый кластер копии MFT.
0x40 1 Кластеров на запись MFT.
0x41 3 Не используется.
0x44 1 Кластеров на индексную запись.
0x45 3 Не используется.
0x48 8 Серийный номер тома. Уникален. Создается в процессе форматирования.
0x50 4 Не используется.
0x54 426 Загрузочный код.
0x1FE 2 Маркер конца. Равен 0xAA55.

Соответствующие структуры имеют вид (определения взяты из исходников Linux-NTFS Project, там же можно найти очень много информации о структурах ntfs). Так же как и FAT, NTFS хранит часть информации в блоке, называемом BIOS Parameter Block, который входит в состав boot sector.

typedef struct _BIOS_PARAMETER_BLOCK
{
/*0x0b*/USHORT bytes_per_sector;	/* Размер сектора, в байтах */
/*0x0d*/UCHAR  sectors_per_cluster;	/* Секторов в кластере */
/*0x0e*/USHORT reserved_sectors;		/* должен быть ноль */
/*0x10*/UCHAR  fats;			/* должен быть ноль */
/*0x11*/USHORT root_entries;		/* должен быть ноль */ 
/*0x13*/USHORT sectors;			/* должен быть ноль */ 
/*0x15*/UCHAR  media_type;		/* тип носителя, 0xf8 = hard disk */
/*0x16*/USHORT sectors_per_fat;		/* должен быть ноль */
/*0x18*/USHORT sectors_per_track;	/* не используется */
/*0x1a*/USHORT heads;			/* не используется */
/*0x1c*/ULONG hidden_sectors;		/* не используется */
/*0x20*/ULONG large_sectors;		/* должен быть ноль */ 
/* sizeof() = 25 (0x19) bytes */
} BIOS_PARAMETER_BLOCK, *PBIOS_PARAMETER_BLOCK;

typedef struct _NTFS_BOOT_SECTOR
{
/*0x00*/UCHAR  jump[3];			/* переход на загрузочный код */
/*0x03*/ULARGE_INTEGER oem_id;	/* сигнатура "NTFS    ". */
/*0x0b*/BIOS_PARAMETER_BLOCK bpb;
/*0x24*/UCHAR physical_drive;		/* не используется */
/*0x25*/UCHAR current_head;		/* не используется */
/*0x26*/UCHAR extended_boot_signature; /* не используется */
/*0x27*/UCHAR reserved2;			/* не используется */
/*0x28*/ULARGE_INTEGER number_of_sectors;	/* Количество секторов на томе. */
/*0x30*/ULARGE_INTEGER mft_lcn;	/* Стартовый кластер MFT. */
/*0x38*/ULARGE_INTEGER mftmirr_lcn;/* Стартовый кластер копии MFT */
/*0x40*/CHAR  clusters_per_mft_record;	/* Размер MFT записи в кластерах. */
/*0x41*/UCHAR  reserved0[3];		/* зарезервировано */
/*0x44*/CHAR  clusters_per_index_record;/* Размер индексной записи в кластерах. */
/*0x45*/UCHAR  reserved1[3];		/* зарезервировано */
/*0x48*/ULARGE_INTEGER volume_serial_number;	/* уникальный серийный номер тома */
/*0x50*/ULONG checksum;			/* не используется */
/*0x54*/UCHAR  bootstrap[426];		/* загрузочный-код */
/*0x1fe*/USHORT end_of_sector_marker;	/* конец загрузочного сектора, сигнатура 0xaa55 */
/* sizeof() = 512 (0x200) bytes */
} NTFS_BOOT_SECTOR, *PNTFS_BOOT_SECTOR;

При проверке факта, что том является NTFS, необходимо прежде всего проверить сигнатуру «NTFS ».

if( NtfsBootSector->oem_id.QuadPart != 0x202020205346544E )
		return FALSE;

Потом некоторые параметры бут сектора, как например кол-во байт в секторе и количество секторов в кластере на кратность двойки в степени.

if( NtfsBootSector->bpb.bytes_per_sector < 0x100 || 
	NtfsBootSector->bpb.bytes_per_sector > 0x1000 ) return FALSE;

//check sectors per cluster
switch( NtfsBootSector->bpb.sectors_per_cluster ) {
	case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:
		break;
	default:
		return FALSE;
}

Все проверки в функции ntfs_boot_sector_is_ntfs из Linux-NTFS Project.

Таблица MFT

Об MFT слышал, наверное, каждый и информация по ней есть и у Руссиновича и в статьях, например у Касперски в «NTFS изнутри и снаружи», все же я продублирую и обобщу ее.

В NTFS ключевым местом для хранения информации о файлах является таблица MFT (Master File Table). В ней содержится информацию обо всех файлах в системе. MFT состоит из записей (mft record) фиксированного размера, размер записи указывается в параметре clusters_per_mft_record структуры бут сектора.

Ключевые моменты NTFS:

  • Любой объект файловой системы представляется хотя бы одной записью в MFT и, по сути, является файлом. Например, бут сектор - файл $Boot, сам MFT – $Mft.
  • Файл представляет собой набор атрибутов, в которых хранятся все данные. Например, атрибут $STANDART_INFORMATION хранит информацию о файле. Атрибутом также являются и данные. Если файл имеет альтернативные потоки (streams), то таких атрибутов несколько, по числу потоков.
  • LCN – смещение в кластерах относительно тома, VCN – смещение в кластерах относительно файла. Для перевода LCN в смещение на томе следует использовать формулу offs = lcn * bytes_per_sector * sectors_per_cluster, соответствующие значения хранятся в BIOS_PARAMETER_BLOCK в бут секторе.

MFT состоит из заголовка записи MFT_RECORD, за которым следуют данные записи – атрибуты.

typedef struct _MFT_RECORD 
{
/*0x00*/	ULONG signature; //сигнатура 'FILE'
/*0x04*/	USHORT usa_offs;
/*0x06*/	USHORT usa_count;
/*0x08*/	ULARGE_INTEGER lsn;
/*0x10*/	USHORT sequence_number;
/*0x12*/	USHORT link_count;
/*0x14*/	USHORT attrs_offset;
/*0x16*/	USHORT flags;//флаги, см. MFT_RECORD_FLAGS 
/*0x18*/	ULONG bytes_in_use;
/*0x1C*/	ULONG bytes_allocated;
/*0x20*/	ULARGE_INTEGER base_mft_record; //адрес базовой MFT-записи
/*0x28*/	USHORT next_attr_instance;
/*0x2A*/	USHORT reserved;
/*0x2C*/	ULONG mft_record_number;
//size - 48 b 
} MFT_RECORD, *PMFT_RECORD;

Начало записи MFT идентифицируется сигнатурой “FILE”. Флаги указывают, является ли запись каталогом, или файлом и используется ли запись вообще.

typedef enum {
	MFT_RECORD_NOT_USED	= 0, //запись не используется
	MFT_RECORD_IN_USE		= 1, //запись используется
	MFT_RECORD_IS_DIRECTORY	= 2 //запись описывает каталог
} MFT_RECORD_FLAGS;

Если файловая запись используется и описывает каталог, тогда поле flags равно MFT_RECORD_IN_USE | MFT_RECORD_IS_DIRECTORY (3). Для файла, flags равен MFT_RECORD_IN_USE.

Записи адресуются через структуру

struct MFT_REF
{
	unsigned __int64 index : 48; //индекс элемента в таблице
	unsigned __int64 ordinal : 16; //порядковый номер
};

Для адресации записей используется младшее поле index, а ordinal нужно для определения несоответствий внутри самой файловой системы.

Смещение первого элемента MFT (в кластерах), т. е. его начало хранится в поле mft_lcn. Размер записи хранится в поле clusters_per_mft_record. Особенность этого поля заключается в том, что оно может хранить отрицательное значение, в таком случае это указание на то, что размер записи задается не в кластерах, а в байтах, причем задается не количество байт, а отрицательное значение степени двойки (логарифм двойки). Для получения количества байт нужно сделать инверсию значения в положительное и возвести двойку в степень этого значения. Например, так.

if( boot_sect.clusters_per_mft_record > 0 ) 
bpmftrec = bps * spc * boot_sect.clusters_per_mft_record;
else
	bpmftrec = 2 << ~boot_sect.clusters_per_mft_record;

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

Первые записи MFT стандартизированы и описывают служебные файлы самой NTFS.

Утилита Руссиновича nfi позволяет сдампить элементы в MFT и просмотреть их атрибуты, например, nfi C.

Содержание Вперёд

NTFS - файловая система, получившая начало в семействе Windows NT и получившая продолжение в новой Windows 7 (обсудить Windows 7 на форуме).

Новости мира IT:

Архив новостей

Последние комментарии:

Вышло обновление Firefox 57.0.1 (1)
Среда 06.12, 09:14

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 985 1945361
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2015 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...