Со временем жесткие диски становились все больше, и DOS должна была уметь работать с ними. Для решения этой задачи разработчики Microsoft реализовали возможность создания на одном физическом диске нескольких разделов или логических дисков. DOS могла форматировать каждый раздел для разных файловых систем (FAT12 или FAT16) и назначать каждому разделу свою букву диска.

Bерсии 3 и 4 DOS были ограничены по размеру и числу разделов, которые они могли создавать, но уже в версии 5 механизм формирования разделов практически не имел ограничений. Диск можно было делить на любое число разделов произвольного размера. Разработчики NT перенесли в новую операционную систему механизм создания разделов DOS, чтобы, с одной стороны, обеспечить совместимость с DOS и Windows 3.1, а с другой, - иметь возможность пользоваться испытанными инструментами управления хранением. В NT была расширена реализованная в DOS поддержка функций, необходимых операционной системе уровня предприятия: формирование наборов томов и обеспечение устойчивости к отказам. Начиная с первой версии NT системные администраторы могли создавать тома, охватывающие разные разделы. Такая возможность позволяла иметь тома большого объема, состоящие из разделов на разных физических дисках, и обеспечивала отказоустойчивость посредством программной реализации избыточности.

Хотя поддержку управления разделами в NT я бы назвал достаточно гибкой и соответствующей большинству задач хранения, все же есть некоторые недостатки. Один из них заключается в том, что для завершения большинства операций по настройке дисковой подсистемы требуется перезагрузка компьютера. В современных условиях, когда от серверов требуется непрерывная работа в течение месяцев, а то и лет, даже плановые остановки доставляют большое неудобство. Другой недостаток связан с тем, что вся информация о расширенных настройках дисков хранится в системном реестре NT. При такой организации хранения настроек неизбежны трудности при переносе данных о конфигурации дисков с одной системы на другую, а при переустановке NT и вовсе легко потерять. Ну и наконец, в NT каждый том должен иметь уникальную букву логического диска, от А до Z, а это условие ограничивает общее количество локальных и удаленных дисков, которые можно использовать.

В Windows 2000 снято большинство ограничений, свойственных NT 4.0, и реализовано много новых функций. Это и точки монтирования томов, устраняющие лимит на количество используемых томов, и интегральная поддержка синхронизации файлов для работы в автономном режиме, и выполнение операций по управлению дисками без перезагрузки, и многое другое. Все эти новации выводят Windows 2000 на один уровень с большинством мощных UNIX-систем. Эта статья, посвященная устройству системы хранения в NT и Windows 2000, состоит из двух частей. В первой части я расскажу об управлении дисками в NT 4.0, в том числе о создании разделов, назначении букв логических дисков, процессе монтирования и деталях программной реализации отказоустойчивости. Во второй части речь пойдет о новых возможностях, реализованных в системе хранения Windows 2000, в частности о менеджере логических дисков Logical Disk Manager (LDM) и reparse points.

Формирование разделов

Как уже было сказано, базой для системы управления дисками в NT 4.0 послужила схема создания разделов из DOS версии 5. Для начала хочу ознакомить читателей с терминами, которыми в дальнейшем буду оперировать. Диском (disk) я буду называть физическое устройство хранения, например жесткий диск, дискету, компакт-диск. Контроллер диска делит диск на сектора - адресуемые блоки фиксированного размера. Для всех систем на базе процессоров x86 размер сектора жесткого диска составляет 512 байт, тогда как для компакт-диска он равен 2048 байт. Томом (volume) я буду называть объект, который объединяет сектора из одного или разных разделов диска, рассматриваемый файловой системой как единое целое. Том обычно ассоциируют с одним разделом, но при создании набора томов или отказоустойчивого тома он состоит из нескольких разделов, нередко даже расположенных на разных дисках. Термин «логический диск» (drive) иногда используется для обозначения и дисков и томов. Во избежание недоразумений я не стану употреблять его в этом контексте.

При установке NT на компьютер первое, что требуется сделать, это создать раздел на первом физическом диске системы. NT формирует в этом разделе системный том и записывает туда файлы, которые использует на ранней стадии процесса загрузки с системного тома. Далее программа установки выдает запрос о формировании раздела, в котором будут размещены файлы операционной системы и создан системный каталог. Этот раздел послужит загрузочным томом, в котором программа установки разместит системные файлы NT и организует корневой каталог (winnt). Один и тот же том может быть и системным томом, и загрузочным. Термины, которые употребляются в документации Microsoft при описании системного и загрузочного томов, немного запутаны и могут ввести в заблуждение. Дело в том, что на системном томе NT размещаются файлы для загрузки, NT Loader (NTLDR) и NTDETECT, а на загрузочном томе хранятся базовые системные файлы, вроде файла ядра ntoskrnl.exe.

Рисунок 1. Пример размещения разделов на диске.

Реализации стандартных BIOS для компьютеров семейства x86 задают одно обязательное требование к формату разделов NT - чтобы первый сектор первого физического диска содержал загрузочную запись Master Boot Record (MBR). При загрузке систем с процессорами х86, BIOS компьютера читает MBR и рассматривает содержимое части сектора как исполняемый код. После выполнения первичной процедуры проверки и конфигурации аппаратного обеспечения, BIOS вызывает код из MBR для инициализации процесса загрузки операционной системы. Для операционных систем Microsoft, в том числе и NT, в MBR находится также и таблица разделов. Она состоит из четырех записей, которые описывают до четырех основных разделов диска. Имеется много предопределенных типов разделов, и тип раздела, который записан в данной таблице, определяет файловую систему этого раздела. Например, для FAT32 и NTFS существуют свои типы разделов. Особый тип раздела, расширенный раздел, или Extended Boot Record (EBR), содержит другую запись MBR со своей таблицей разделов. Использование расширенного раздела позволяет преодолеть ограничение операционных систем Microsoft по количеству разделов (не более четырех на диск), накладываемое таблицей разделов в MBR. В общем случае, рекурсия в формировании расширенных разделов может выполняться бесконечно, а значит, на диске может быть создано множество разделов. Примерная схема размещения разделов показана на Рисунке 1.

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

Драйверы хранения и объекты устройств

За выполнение первого этапа процесса загрузки NT отвечает загрузчик NTLDR. Он расположен на системном томе и вызывается программой из загрузочного сектора. NTLDR считывает файл boot.ini на системном томе и предлагает пользователю варианты загрузки. Имена разделов в файле boot.ini записываются в виде multi(0)disk(0)rdisk(0)partition(1). Такой вариант именования соответствует правилам Advanced RISC Computing (ARC), которые входят в стандартную схему именования разделов в системах Alpha и других RISC-системах. NTLDR ставит имя выбранного пользователем раздела из файла boot.ini в соответствие загрузочному разделу и загружает с указанного раздела системные файлы NT в память (начиная с реестра, ntoskrnl.exe и загрузочных драйверов), продолжая процесс загрузки.

При инициализации ядро NT запускает драйверы хранения для жесткого диска. Эти драйверы выполнены в архитектуре класс - порт - мини-порт. Это означает, что Microsoft выпускает драйвер класса, реализующий общие функции для всех устройств хранения, и драйвер порта, поддерживающий функции, специфичные для конкретной шины (т. е. SCSI, IDE). OEM-поставщики добавляют драйверы мини-порта, которые объединяются с драйвером порта, обеспечивающим интерфейс к конкретным устройствам. Например, Adaptec поставляет SCSI-драйверы мини-порта для различных выпускаемых ею SCSI-контроллеров. Такое разделение ролей приносит двойную выгоду. Во-первых, разработчик драйвера мини-порта имеет дело со знакомой средой, а не с более сложной средой драйверов NT. Во-вторых, Microsoft поставляет драйверы класса и порта для Windows 9x, что позволяет использовать написанные разработчиком драйверов мини-порта для NT на платформе Windows 9x и наоборот.

Так как драйверы мини-порта передают драйверу класса информацию о дисках, которые они идентифицировали ранее при загрузке, то менеджер ввода/вывода NT, I/O Manager, включает в себя функцию IoReadPartitionTable, которую драйвер класса вызывает для каждого диска. Далее уже эта функция вызывает функцию чтения-записи дискового уровня, которую представляют драйверы класса, порта и мини-порта, для формирования внутреннего представления структуры дисковых разделов. Драйвер класса Disk создает объекты устройств для представления каждого первичного раздела (в том числе первичных разделов внутри расширенных), информацию о которых получает от IoReadPartitionTable. Драйверы устройств пользуются объектами для обращения к физическим и логическим устройствам, включая диски, клавиатуру и интерфейсы управления устройствами. Такие драйверы могут именовать объекты, и другие устройства и приложения могут открывать объекты и посылать им запросы на чтение-запись. Драйвер класса Disk создает каталог Hardisk X (где X - номер диска, присвоенный ему NT) в пространстве имен NT Object Manager для каждого жесткого диска. Далее драйвер класса Disk помещает объекты раздела в каталог HardiskX того диска, на котором эти объекты располагаются. Например, на Экране 1 показано содержимое каталога device harddisk0 компьютера, первый жесткий диск которого разбит на четыре раздела, представленных объектами в правой половине окна. Драйвер класса Disk дает объекту, представляющему весь физический диск, имя partition0.

Когда бы драйвер устройства или приложение ни послали запрос на чтение-запись объекту устройства, менеджер NT I/O Manager перенаправляет его (в виде программного пакета с запросом на чтение-запись - I/O request Packet, IRP) тому драйверу устройства, который создал данный объект. Так, перед тем, как послать запрос на чтение загрузочный сектор на втором разделе harddisk0, приложение сначала открывает объект deviceharddisk0partition2, затем посылает ему запрос на чтение 512 байт, начиная со смещения 0. NT I/O Manager перенаправляет запрос приложения драйверу класса Disk, сообщая, что IRP предназначен для объекта partition2. Поскольку разделы есть не более чем логические представления, применяемые в NT для доступа к непрерывным зонам на физическом диске, драйвер класса должен перевести смещения, которые отсчитываются относительно раздела, в смещения, отсчитываемые от начала диска. Если partition2 начинается с сектора диска №4096, драйверу класса следует подстроить параметры IRP и задать именно этот номер как смещение, прежде чем пересылать запрос драйверу мини-порта. Драйвер мини-порта выполняет операции чтения-записи на физическом диске и возвращает запрошенные данные в буфер приложения, указанного в IRP.

Интерфейс Win32 API не имеет представления о пространстве имен NT Object Manager. NT резервирует пару разных подкаталогов в пространстве имен для использования Win32 и именует один из них как ??. В этом подкаталоге NT делает доступными объекты устройств, с которыми взаимодействуют приложения Win32, включая COM и параллельные порты, а также диски. Поскольку объекты диска реально размещены в других каталогах, NT применяет символические ссылки для связи объектов, расположенных внутри каталога ??, с объектами, расположенными где-либо еще в пространстве имен. Для каждого физического диска системы I/O Manager создает ссылку ??PhysicalDriveX, которая указывает на deviceharddiskXpartition0 (Х заменяют на номер, начиная от 0). Приложения Win32, работающие с секторами диска напрямую, открывают диск, указывая имя \.PhysicalDriveX (где Х - номер диска) и вызывая Win32 CreateFile. На уровне приложений Win32 имя конвертируется в ??PhysicalDriveX, перед тем как будет передано NT Object Manager.

Назначение имен

После инициализации драйверов хранения диска NT Object Manager вызывает внутреннюю функцию IoAssignDriveLetters. Эта функция формирует символическую ссылку буквы имени диска на раздел в каталоге ??, в том числе для компакт-диска и 3,5-дюймовых дискет. Такие ссылки соотносятся с соответствующими объектами устройств раздела. I/O Manager присваивает имена стандартным способом, но можно задавать дискам нужные буквы и через Disk Administrator. При запуске Disk Administrator, программа сканирует разделы жестких дисков системы и генерирует произвольные сигнатуры для тех из них, что появились с момента последнего выполнения Disk Administrator. Эти сигнатуры содержатся в загрузочном секторе раздела и в разделе реестра HKEY_LOCAL_MACHINESYSTEMDISKInformation, где хранятся структура каждого раздела диска и буква, выделенная для раздела. Функция IoAssign DriveLetters считывает информацию из раздела Information и узнает о назначенной диску букве, перед тем как присвоить имя по умолчанию. Далее эта функция читает сигнатуры разделов и соотносит их с данными в Information для связи разделов и их букв.

После того как IoAssignDriveLetters назначит буквы явно заданным разделам, она начинает присваивать буквы первым активным разделам каждого диска (начиная с С или первой неназначенной после С буквы). Если на диске нет активного основного раздела, IoAssign DriveLetters назначает букву первому основному разделу. Последовательно выполняя присваивание, IoAssignDriveLetters назначает буквы каждому разделу в расширенных разделах диска. В конце IoAssign DriveLetters присваивает буквы всем оставшимся первичным разделам.

После создания символических связей букв и разделов жесткого диска IoAssignDriveLetters дает имена 3,5-дюймовому диску и компакт-диску. Два первых 3,5-дюймовых диска получают буквы А и В, все прочие - оставшиеся свободными буквы. Назначить буквы компакт-дискам можно в Disk Administrator, но, прежде чем сохранить их в разделе Information реестра, Disk Administrator присваивает эти буквы специальным параметрам, которые имеют такие же имена, как и объекты устройств, соответствующие в NT компакт-диску. Например, система с одним компакт-диском и назначенной ему буквой будет иметь в реестре параметр devicecdrom0 внутри HKEY_ LOCAL_MACHINESYSTEMDISK, указывающий на заданную компакт-диску букву. На Экране 2 показано содержимое каталога ?? в Object Manager и выделена символическая ссылка для С.

Экран 2. Просмотр символических ссылок на жесткие диски системы.

Монтирование файловой системы

Если NT назначила разделу букву, это вовсе не означает, что он содержит данные, организованные в формате файловой системы, которую понимает NT. Процесс опознавания тома включает этап подтверждения файловой системой владения разделом; это происходит в тот момент, когда ядро, драйвер устройства или приложение осуществляют доступ к файлу или каталогу в разделе. После того как драйвер файловой системы подтвердит свою ответственность за раздел, I/O Manager отсылает все запросы IRP, направленные к данному разделу, драйверу, отвечающему за него. Операция монтирования в NT 4.0 опирается на три компонента: регистрацию драйвера файловой системы, блоки Volume Parameter Blocks (VPB) и запрос на монтирование.

Менеджер ввода/вывода, I/O Manager, отвечает за процесс монтирования, и «знает» обо всех доступных драйверах файловой системы, поскольку при инициализации они регистрируются именно им. Этот же менеджер реализует функцию IoRegisterFileSystem, с помощью которой происходит регистрация драйверов файловой системы локального диска (но не сетевого). После регистрации драйвера файловой системы I/O Manager сохраняет ссылку на драйвер в своем списке, который в дальнейшем используется для операций монтирования.

Каждый объект устройства содержит структуру данных VPB, но I/O Manager рассматривает блоки VPB только как объекты устройства «раздел». VPB выступает в качестве соединителя между объектом «раздел» и объектом устройства, которое представляет данный раздел после монтирования и создает драйвер файловой системы. Если ссылки на файловую систему в VPB нет, то данный раздел не подсоединен ни к какой файловой системе. Менеджер I/O Manager проверяет объект VPB устройства «раздел» всякий раз, когда происходит вызов API, указывающий имя файла или каталога на разделе, обслуживаемом объектом. Например, если I/O Manager назначил букву D второму разделу на первом жестком диске системы, IoAssignDriveLetters создает ссылку ??D:, которая указывает на объект deviceharddisk0partition2. Приложение Win32, пытаясь открыть файл est на D, указывает имя D: est, которое подсистема Win32 конвертирует в ??D: est, прежде чем вызвать NtCteateFile - процедуру ядра для открытия файла. NtCteateFile использует ObjectManager для разбора имени, и тот обнаруживает, что объект устройства device harddisk0partition2 с путем est неопределен. В этот момент I/O Manager ищет в VPB device harddisk0partition2 ссылки на файловую систему. Если их нет, то менеджер выдает запрос на монтирование каждому зарегистрированному драйверу файловой системы, спрашивая драйвер, не может ли он опознать формат раздела. Если драйвер выдает подтверждение, то I/O Manager заполняет блоки VPB и передает ему открытый запрос с оставшимся путем (т. е. est). Далее уже данный драйвер файловой системы завершает запрос, используя формат соответствующей файловой системы для интерпретации хранящихся в разделе данных. Если ни один из драйверов файловой системы не опознает раздел, то встроенный драйвер NT, именуемый RAW, признает его своим и отвергает все запросы на открытие файлов на этом разделе. На Рисунке 2 в упрощенном виде (пропущено взаимодействие драйвера файловой системы с менеджером NT Cache Manager) приведена схема пути, по которому проходит запрос чтения-записи к смонтированному разделу.

Рисунок 2. Путь запроса чтения-записи к смонтированному разделу.

Исключая загрузочный том, который монтируется при инициализации ядра, драйверы файловой системы подсоединяют большинство томов при запуске Chkdsk, когда при загрузке выводится голубой экран. Chkdsk перебирает все буквы дисков на предмет поиска тома, которому необходима проверка. Для сменных носителей (3,5-дюймовых дискет, например) монтирование одного диска может происходить несколько раз. Два драйвера файловой системы, которые поддерживают сменные носители, CD-ROM File System (CDFS) и FAT, определяют по метке тома, произошла ли смена носителя. Если драйвер обнаруживает другую метку, то он размонтирует старый диск и пытается смонтировать новый.

Устойчивость к сбоям

Архитектура чтения-записи NT обладает возможностью динамического связывания объектов устройств. Драйвер устройства может создать объект устройства и подсоединить его к целевому объекту. I/O Manager перенаправляет запросы к присоединенному целевому объекту, если таковой существует. Драйверы устройств применяют этот механизм для наблюдения или изменения поведения объектов, принадлежащих другим драйверам устройств. Драйвер, который выполняет присоединение, называется фильтром (Filter driver), и при получении запроса IRP к целевому устройству имеет полный контроль над ним. Фильтр может отвергнуть запрос, создать новые подзапросы или просто передать запрос целевому устройству без изменений. Драйверы хранения NT используют такие слои объектов в трех местах. На высшем уровне драйверы фильтра файловой системы присоединяются к объектам целевого устройства, которые представляют смонтированные разделы, созданные драйверами файловой системы. Драйвер фильтра может таким образом отслеживать запросы, направленные к смонтированным томам, что позволяет реализовывать функции аудита, шифрования или проверки на вирус в процессе доступа.

При запуске счетчиков производительности NT (с помощью команды Diskperf -y) происходит установка драйвера фильтра Diskperf. Он присоединяется к объектам, которые представляют физические диски (например, deviceharddisk0 partition0), и может собирать статистику для представления в Performance Monitor. При создании с помощью Disk Administrator нестандартного тома - набора томов, зеркального тома, чередующегося набора или чередующегося набора с четностью - включается фильтр FtDisk.

Набор томов - том, использующий более одного раздела для формирования одного протяженного. Можно использовать разделы с разных дисков для создания набора томов, большего по объему, чем любой имеющийся на компьютере физический диск. Зеркальный том содержит копии своих данных на двух разделах. В случае зеркала запись данных производится на оба раздела, а считывание происходит только с одного. Зеркальный том устойчив к сбою одного диска, в этом случае работает оставшаяся половина. Чередующийся набор томов - том, состоящий из нескольких разделов, по которым равномерными блоками распределены данные. NT использует блоки данных по 64 Кбайт. Первый блок данных размером в 64 Кбайт хранится на первом разделе, вторые 64 Кбайт на втором и т.д. по кругу, возвращаясь к первому разделу. Чередующиеся наборы томов могут повысить производительность системы, если использовать разделы, размещенные на разных дисках, поскольку операции чтения-записи могут выполняться параллельно. Ну и наконец, чередующийся набор томов с четностью - это чередующийся набор с дополнительным блоком данных размером в 64 Кбайт для разделов, образующих чередующийся набор. Дополнительный блок содержит информацию о четности, которую система NT может использовать при восстановлении данных, расположенных на одном из разделов чередующегося набора, в случае выхода из строя диска, где был расположен раздел. Данный набор томов известен как том уровня RAID 5.

Программа Disk Administrator сохраняет подробную информацию о конфигурации томов в разделе HKEY_LOCAL_MACHINESYSTEMDISKInformation, вместе с буквами дисков и сигнатурой, и драйвер FtDisk считывает эти данные при загрузке. Управляемая через FtDisk структура данных в разделе Information связывает разрозненные разделы в один том. Если FtDisk не используется, драйверы файловой системы исходят из того, что содержимое тома расположено в одном разделе, и не могут распознать тома, состоящие из нескольких разделов. Следовательно, FtDisk присоединяется к объектам каждого раздела системы для обслуживания запросов к объектам, формирующим сложные виды томов.

Несколько примеров работы FtDisk помогут прояснить его роль. Если чередующийся набор состоит из deviceharddisk0partition2 и из deviceharddisk1partition3, как показано на Рисунке 3, и набору назначена буква D, то I/O Manager задает связь ??D: для ссылки на deviceharddisk0partition2. Если FtDisk отсутствует, то приложение при открытии файла на чередующемся наборе получит сообщение об ошибке, так как файловая система «не признала» или не смогла смонтировать указанный том, который представлен в deviceharddisk0partition2. При наличии FtDisk созданный им объект перехватывает вызовы подсистемы ввода/вывода файловой системы, направленные к device harddisk0partition2, и драйвер FtDisk вносит необходимые изменения в запрос, прежде чем передать его драйверу класса Disk. Изменения, которые производит FtDisk, задают для запроса правильные величины смещений на целевом чередующемся томе либо в deviceharddisk0partition2, либо в deviceharddisk1partition3.

Рисунок 3. Пример работы FtDisk в случае чтения-записи на чередующемся томе.

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

В следующей части статьи я расскажу о том, как устроена система хранения в Windows 2000, в частности представлю менеджер логических дисков LDM и reparse points.

МАРК РУСИНОВИЧ

доктор философии в области вычислительной техники Университета Карнеги-Меллон и один из соавторов многих популярных утилит для Windows NT, включая NTFSDOS, Filemon, Regmon и Recover. С ним можно связаться по электронной почте по адресу: mark@sysinternals.com, или через Web-узел http://www.sysinternals.com.