Любой, кто хоть раз открывал встроенный редактор реестра, видел пять корневых веток с загадочными сокращениями HKEY. Меньше людей знает, что вся эта гигантская иерархия на самом деле хранится в нескольких отдельных файлах, которые разработчики внутри Microsoft называли ульями. И совсем немногие слышали корпоративную байку, по которой это название якобы появилось в насмешку над одним из менеджеров команды, который не выносил пчёл. Ниже разбирается и техническая начинка реестра, и легенда, и то, как Microsoft сперва поставила всю систему на один карточный домик из тонких перегородок, а потом потихоньку отступала от этой затеи.
Реестр вырос из скромного сервиса регистрации в полноценную базу конфигураций
Реестр появился не сразу и не сразу в том виде, в каком его знают. В Windows 3.1 в 1992 году он существовал в примитивной форме и решал узкую задачу: регистрацию расширений файлов и объектов COM, чтобы система понимала, какая программа отвечает за какой тип данных. Настройки же приложений по старинке лежали в текстовых файлах INI, разбросанных по системе. Настоящий перелом случился в 1993 году с выходом Windows NT 3.1, где реестр был переосмыслен как иерархическая база данных, призванная собрать под одной крышей конфигурацию ядра, драйверов, служб, пользователей и программ. Задумка была соблазнительная: вместо сотни текстовых файлов одно дерево, одно место поиска, один инструмент. Правда, соблазн быстро обернулся и слабостью: единое место хранения означает единую точку отказа.
Корневые разделы реестра и кто за что отвечает в пятёрке HKEY
Открывая редактор, пользователь видит пять корневых разделов, и у каждого своя роль. HKEY_LOCAL_MACHINE хранит параметры машины в целом, от драйверов до служб и установленных программ. HKEY_CURRENT_USER отражает настройки той учётной записи, которая вошла в систему прямо сейчас, причём физически это просто ссылка на соответствующий подраздел внутри HKEY_USERS. HKEY_CLASSES_ROOT объединяет регистрацию типов файлов и COM-объектов, по сути это объединённое представление двух других веток. HKEY_USERS содержит профили всех загруженных пользователей, а HKEY_CURRENT_CONFIG хранит текущую аппаратную конфигурацию, собранную при загрузке. Часть веток вообще не существует как отдельный файл: они виртуальны и собираются системой на лету из реальных источников, что поначалу сбивает тех, кто привык мыслить файлами на диске.
Откуда в реестре пчёлы и почему легенду стоит делить пополам со скепсисом
Теперь к байке, ради которой многие и открывают эту тему. Ульем в терминологии разработчиков NT называется целостный файл реестра, корень отдельной ветки, со своим заголовком и собственной структурой внутри. По воспоминаниям ветеранов Microsoft, которые много лет пересказывал в своих заметках Рэймонд Чен, по одной из версий среди менеджеров команды был человек, испытывавший сильную неприязнь к пчёлам. Коллеги, по этой версии, не упускали случая поддеть его и даже вставили изображение пчелы на скрытую страницу внутренней документации. А когда потребовалось имя для древовидных файлов реестра, слово hive прозвучало отчасти как продолжение той же шутки. Важно держать в уме, что документального подтверждения этой истории нет, она живёт именно как корпоративная легенда из уст в уста. Скептики замечают, что метафора и без шутки напрашивалась: улей состоит из одинаковых сот, а файл реестра из одинаковых блоков, и оба так или иначе полны шевелящегося содержимого. Где шутка, а где структурная загадка, решать уже читателю.
Где физически лежат ульи и как устроен каждый файл изнутри
Реальные ульи системы лежат в каталоге %SystemRoot%\System32\config. Там можно увидеть файлы SAM, SECURITY, SOFTWARE, SYSTEM и DEFAULT, у которых нет привычных расширений. Настройки отдельного пользователя хранятся в его профиле в файле NTUSER.DAT, который монтируется в реестр при входе в систему и становится веткой HKEY_CURRENT_USER. Внутри каждый файл улья начинается с заголовка, где по нулевому смещению стоит сигнатура regf, по которой система узнаёт родной формат. Дальше файл разбит на контейнеры hbin объёмом по 4096 байт каждый, а уже внутри контейнеров размещаются ячейки разных типов. Ячейки nk описывают ключи, vk хранят значения параметров, sk отвечают за дескрипторы безопасности с правами доступа. Связи между ключами организованы наподобие B-дерева, поэтому поиск по ветке не превращается в линейный перебор даже при сотнях тысяч разделов. Для удалённого пространства ведутся карты свободных дыр, так что файл может расти и лоскутиться, но система знает, куда писать. Понять логику помогает простое сопоставление:
- Файл улья это контейнер с заголовком regf и цепочкой блоков hbin;
- Ключ в редакторе соответствует ячейке nk со ссылками на подразделы;
- Параметр с данными в правой панели соответствует ячейке vk;
- Права доступа к ветке сидят в ячейке sk;
- Свободные области файла учитываются отдельными списками для повторного использования.
Два редактора в эпоху NT и их позднее слияние в один инструмент
Долгие годы в Windows сосуществовали сразу два редактора реестра, regedit и regedt32, и это было не дизайнерским капризом. Первый пришёл из старой линейки систем и умел искать по дереву, но не понимал разрешений безопасности и части типов данных NT. Второй, regedt32, работал с списками контроля доступа и типами вроде REG_MULTI_SZ, зато поиска в нём не было вовсе, а неверная правка многострочных значений могла больно ударить по системе. Администраторы жонглировали обоими, в зависимости от задачи. Только в Windows XP это противоречие убрали: возможности regedt32 были перенесены в обновлённый regedit, а имя второго редактора осталось лишь как тонкая обёртка-заглушка, запускающая первый. Такой фокус с честным сохранением старой команды напоминает, сколько в операционной системе держится на привычках её пользователей.
Заглянув глубже в формат, можно увидеть, насколько бережно авторы подошли к надёжности. Каждый блок hbin после своего заголовка несёт последовательность ячеек, а размер каждой ячейки записан со знаком: отрицательный размер означает занятую ячейку, положительный свободную. Благодаря этому при удалении ключа или параметра освободившееся место не пропадает, а помечается как дыра, пригодная для повторного использования. Соседние дыры склеиваются, иначе файл расплылся бы снежным комом от постоянных перестановок. В заголовке regf хранятся номер последовательности, контрольные сведения и указатели на корневую ячейку, от которой система начинает обход дерева. Если при записи заголовка питание пропало на середине, при следующем монтировании номера последовательности не сойдутся, и движок конфигураций поймёт, что копия испорчена, и обратится к журналу либо к резерву. Каждая ветка при открытии задействует дескрипторы безопасности из ячеек sk, а значит даже обычное чтение значения проходит проверку прав, как и любой другой объект операционной системы. Отдельно любопытны списки подразделов: когда у ключа тысячи детей, они оформляются в хэш-списки для быстрого поиска по имени, иначе открытие популярной ветки занимало бы заметное время. Эта развесистая внутренняя механика объясняет, почему операции с реестром на больших деревьях работают бодрее, чем разбор разбросанных текстовых INI-файлов, при всей внешней простоте дерева.
Журналы, восстановление после сбоя и последняя удачная конфигурация
Отдельной заботой разработчиков стала живучесть реестра при внезапной потере питания или сбое драйвера. Рядом с файлами ульев в том же каталоге лежат сопутствующие файлы с суффиксом .log, куда изменения сперва попадают журнально. Запись происходит так, что в любой момент обрыва можно доиграть недописанные операции или откатить недовнесённые, не разрушив структуру. Сверх этого система запоминает последнюю конфигурацию, при которой загрузка прошла успешно. Если очередной старт заканчивается синим экраном, загрузчик предлагает вариант Last Known Good Configuration, откатывающий ветку с параметрами драйверов и служб к последнему удачному состоянию. Связка журналирования и этой резервной копии не раз выручала администраторов в ситуациях, когда свежий драйвер приносил на тестовой машине только печаль и перезагрузки.
Линейка массовых систем догнала идею чуть позже: Windows 95 в 1995 году уже опиралась на реестр как на главное хранилище настроек, а его файлы SYSTEM.DAT и USER.DAT прятались в каталоге Windows. С переходом домашних версий на ядро NT различия сгладились, и формат regf стал общим наследием. В 64-разрядных выпусках появилась ещё одна деталь, о которую спотыкаются администраторы: перенаправление для старых 32-битных программ, чьи обращения к части веток тихо переносятся в подраздел Wow6432Node. Снаружи это выглядит как одинаковое дерево, а внутри программа и система могут видеть разные значения одного и того же ключа. К этому периоду относится и механизм транзакций реестра из Windows Vista, позволявший группировать правки так, чтобы они либо применились целиком, либо не применились вовсе. Идея была красивая, инструмент работал, но повального внимания разработчиков не снискал, и о нём теперь вспоминают редко. Зато о нём вспоминают исследователи форматов, когда разбирают ульи по косточкам в лабораториях.
Любопытно, что сама система наладила и дополнительную подстраховку: регулярное задание архивировало копии ульев в отдельный подкаталог RegBack, откуда их позволялось вернуть даже из среды восстановления, когда основная система не стартует. Администраторы пользуются и офлайн-приёмом: команда reg load подключает чужой файл улья временной веткой, позволяя править настройки упавшей установки, скажем снять с диска больного компьютера файл SYSTEM и внести исправление в редакторе на здоровой машине. Эти инструменты не раз спасали смелые эксперименты с драйверами от полной переустановки.
Единая точка отказа и почему Microsoft стала отходить от реестра
С годами стало ясно, что концентрация настроек в бинарных хранилищах дорого обходится. Повреждённый улей SYSTEM мог не дать машине вообще загрузиться. Приложения плодили разделы, забывали убирать за собой при удалении, и реестр обрастал наследием старых инсталляторов. Удалённое администрирование усложнял необходимый доступ к веткам, а права на ячейках sk приходилось выверять вручную. Одна неудачная правка ветки с параметрами загрузки могла обойтись дороже, чем переустановка, и скорость такого отказа впечатляла даже опытных специалистов. В ответ индустрия потихоньку начала разворот: прикладные настройки уехали в XML-конфигурацию, появились отдельные хранилища в профилях пользователей, а исключительно системная информация осталась за реестром. Такая эволюция показательна: идея собрать всё в одном дереве была красива на бумаге, но жизнь потребовала не только единого склада, но и маленьких мешочков рядом.
Отдельно заметен интерес к формату со стороны специалистов по цифровой криминалистике: по ячейкам улья восстанавливают историю подключённых устройств, список недавних документов и время последней правки ключа. То, что для пользователя просто дерево настроек, для исследователя превращается в датированный дневник машины. Это ещё одно напоминание, что реестр видел буквально всё, что происходило в системе.
Ульи пережили три десятилетия и по-прежнему лежат в System32\config в каждой свежей установке Windows. Внутри они по-прежнему построены из тех же hbin и ячеек, журналы по-прежнему подстраховывают запись, а где-то во внутренней хронике Microsoft, возможно, до сих пор хранится та самая скрытая страница с пчелой. Удачная метафора живёт долго, а если она ещё и технически точно описывает хранилище, такая задумка прилипает надолго. Возможно, именно поэтому пчёлы из корпоративной байки так и продолжают гудеть внутри System32\config, не подозревая, что их улей держит на себе всю загрузку очередной машины, пока владелец ждёт появления рабочего стола.