Ресурсы Windows
 
   Ресурсы Windows (Windows Resource Kits) расширяют Support Tools, предлагая дополнительные утилиты для администрирования и поддержки систем. Утилиты Windows Server 2003 Resource Kit можно бесплатно скачать с microsoft.com (выполните поиск по ключевым словам «resource kit tools»). Их можно установить в Windows XP или Windows Server 2003.
   Ресурсы Windows 2000 существуют в двух изданиях: Windows 2000 Professional Resource Kit и Windows 2000 Server Resource Kit* (самая последняя
   Последнее издание переведено на русский язык издательством «Русская Редакция» и выпущено в 2001 г. в виде серии «Ресурсы Microsoft Windows 2000 Server» которая включает 4 книги: «Сети TCP/IP», «Сопровождение сервера», «Распределенные системы» и «Межсетевое взаимодействие». - Прим. перев.
   его версия - Supplement 1). Хотя последний набор представляет собой надмножество первого и может быть установлен на системах с Windows 2000 Professional, утилиты, входящие только в Windows 2000 Server Resource Kit, ни в одном из наших экспериментов не используются. B отличие от утилит Windows Server 2003 Resource Kit эти утилиты нельзя скачать бесплатно. Однако Windows 2000 Server Resource Kit поставляется с подписками на MSDN и TechNet.
 
Отладка ядра
 
   Отладка ядра подразумевает изучение внутренних структур данных ядра и/ или пошаговый проход по функциям в ядре. Это полезный способ исследования внутреннего устройства Windows, потому что он позволяет увидеть внутрисистемную информацию, недоступную при использовании каких-либо других способов, и получить более ясное представление о схеме выполнения кода внутри ядра.
   Отладку ядра можно проводить с помощью разнообразных утилит: Windows Debugging Tools от Microsoft, LiveKD от wwwsysinternals.com или SoftIce от Compuware NuMega. Прежде чем описывать эти средства, давайте рассмотрим файл, который понадобится при любом виде отладки ядра.
 
Символы для отладки ядра
 
   Файлы символов (symbol files) содержат имена функций и переменных. Они генерируются компоновщиком (linker) и используются отладчиками для ссылки и отображения этих имен в сеансе отладки. Эта информация обычно не хранится в двоичном образе, потому что она не нужна при выполнении кода. To есть двоичные образы имеют меньший размер и работают быстрее. Ho это означает, что вам нужно позаботиться о том, чтобы у отладчика был доступ к файлам символов, сопоставляемым с образами, на которые вы ссылаетесь в сеансе отладки.
   Для изучения внутренних структур данных ядра Windows (например, списка процессов, блоков потока, списка загруженных драйверов, информации об использовании памяти и т. д.) вам понадобятся подходящие файлы символов как минимум для образа ядра, Ntoskrnl.exe. (Подробнее этот файл рассматривается в разделе «Обзор архитектуры» главы 2.) Файлы таблиц символов должны соответствовать версии образа. Так, если вы установили Windows Service Pack или какое-то оперативное исправление, то должны получить обновленные файлы символов хотя бы для образа ядра; иначе возникнет ошибка из-за неправильной контрольной суммы при попытке отладчика ядра загрузить их.
   Хотя можно скачать и установить символы для разных версий Windows, обновленные символы для оперативных исправлений доступны не всегда. Самый простой способ получить подходящую версию символов для отладки - обратиться к Microsoft-серверу символов с запросом, в котором используется специальный синтаксис пути к символам, как в отладчике. Например,
   следующий путь к символам заставляет средства отладки загружать требуемые символы с Интернет-сервера символов и сохранять локальную копию в папке c:\symbols:
    srv*c:\symbols* http://msdl.microsoft.com/downloacl/symbols
   Подробные инструкции о том, как пользоваться сервером символов, см. в справочном файле Debugging Tools или на Web-странице wwwmicrosoft. com/whdc/ddk/debugging/symbols.mspx.
 
Windows Debugging Tools
 
   Пакет Windows Debugging Tools содержит дополнительные средства отладки, применяемые в этой книге для исследования внутреннего устройства Windows. Вы найдете их последние версии по ссылке www.microsoft.com/ whdc/ddk/debugging.Эти средства можно использовать для отладки как процессов пользовательского режима, так и ядра (см. следующую врезку).
 
    ПРИМЕЧАНИЕWindows Debugging Tools регулярно обновляются и выпускаются независимо от версий операционной системы Windows, поэтому почаще проверяйте наличие новых версий отладочных средств.
 
Отладка в пользовательском режиме
 
   Средства отладки можно подключать к процессу пользовательского режима, чтобы исследовать и/или изменять память процесса. Существует два варианта подключения к процессу:
    (o) Invasive (инвазивный)Если не указано иное, то, когда вы подключаетесь к выполняемому процессу, Windows-функция DebugAc-tiveProcess устанавливает соединение между отладчиком и отлаживаемым процессом. Это позволяет изучать и/или изменять память процесса, устанавливать точки прерывания (breakpoints) и выполнять другие отладочные действия. B Windows 2000 при завершении отладчика закрывается и отлаживаемый процесс. Однако в Windows XP отладчик можно отключать, не уничтожая целевой процесс.
    (o) Noninvasive (неинвазивный)B этом случае отладчик просто открывает процесс через функцию OpenProcess. Он не подключается к процессу как отладчик Это позволяет изучать и/или изменять память целевого процесса, но не дает возможности устанавливать точки прерывания. Преимущество данного варианта в том, что в Windows 2000 можно закрыть отладчик, не завершая целевой процесс.
   C помощью отладочных средств также можно открывать файлы дампов процессов пользовательского режима. Что представляют собой эти файлы, поясняется в главе 3 в разделе по диспетчеризации исключений.
   Microsoft предлагает отладчики ядра в двух версиях: командной строки (Kd.exe) и с графическим пользовательским интерфейсом p^indbg.exe). Оба
   инструмента предоставляют одинаковый набор команд, так что выбор конкретной утилиты определяется сугубо личными пристрастиями. C помощью этих средств вы можете вести отладку ядра в трех режимах.
    (o)Откройте файл дампа, полученный в результате краха системы с Windows (подробнее о таких дампах см. главу 14).
    (o)Подключитесь к работающей системе и изучите ее состояние (или поставьте точки прерывания, если вы отлаживаете код драйвера устройства). Эта операция требует двух компьютеров - целевого и управляющего. Целевой считается отлаживаемая система, а управляющей - та, в которой выполняется отладчик. Целевая система может быть либо локальной (соединенной с управляющей нуль-модемным кабелем или по IEEE 1394), либо удаленной (соединенной по модему). Вы должны загрузить целевую систему со спецификатором /DEBUG, или нажать при загрузке клавишу F8 и выбрать Debug Mode, или добавить соответствующую запись в файл Boot.ini.
    (o)B случае Windows XP и Windows Server 2003 подключитесь к локальной системе и изучите ее состояние. Это называется локальной отладкой ядра.Чтобы инициировать такую отладку ядра, выберите в меню FiIe команду Kernel Debug, перейдите на вкладку Local и щелкните ОК. Пример окна с выводом показан на рис. 1-7. Некоторые команды отладчика ядра в этом режиме не работают (например, просмотр стеков ядра и создание дампа памяти командой .dump невозможны). Однако вы можете пользоваться бесплатной утилитой LiveKd с сайта wwwsysinternals.com в тех случаях, когда родные средства локальной отладки не срабатывают (см. следующий раздел).
   Подключившись в режиме отладки ядра, вы можете использовать одну из многих команд расширения отладчика (команды, которые начинаются с «!») для вывода содержимого внутренних структур данных, например потоков, процессов, пакетов запроса на ввод-вывод и информации, связанной с управлением памятью. Команды отладчика ядра и их вывод будут обсуждаться при рассмотрении соответствующей тематики. A пока добавим, что команда dt(display type) может форматировать свыше 400 структур ядра благодаря тому, что файлы символов ядра для Windows 2000 Service Pack 3, Windows XP и Windows Server 2003 содержат информацию о типах, которая и позволяет отладчику форматировать структуры.
 
    ЭКСПЕРИМЕНТ: отображение информации о типах для структур ядра
   Чтобы вывести список структур ядра, чья информация о типах включена в символы ядра, наберите dt nt!_*в отладчике ядра. Пример части вывода показан ниже:
   Команда dtпозволяет искать конкретные структуры по шаблонам. Например, если вы ищете имя структуры для объекта прерывания (interrupt object), введите dt nt!*interrupt*:
   Заметьте, что по умолчанию dtне показывает подструктуры (структуры внутри структур). Для рекурсивного прохода по подструктурам, используйте ключ -r.Например, указав этот ключ для отображения объекта ядра «прерывание», вы увидите формат структуры _LIST_ENTRY, хранящейся в поле InterruptListEntry:
   B справочном файле Windows Debugging Tools объясняется, как устанавливать и использовать отладчики ядра. Дополнительные сведения о применении отладчиков ядра, предназначенных в основном разработчикам драйверов устройств, см. в документации Windows DDK. Есть также несколько полезных статей в Knowledge Base по отладчикам ядра. Выполните поиск по ключевому слову «debugref» в Windows Knowledge Base (онлайновой базе данных технических статей) на supportmicrosoft.com .
 
Утилита LiveKd
 
   LiveKd - бесплатная утилита ,которая позволяет использовать стандартные отладчики ядра от Microsoft на «живой» системе - без подключения второго компьютера. Если встроенная поддержка локальной отладки ядра действует только в Windows XP и Windows Server 2003, то LiveKd обеспечивает такую отладку в Windows NT 4.0, Windows 2000, Windows XP и Windows Server 2003.
   LiveKd запускается точно так же, как Windbg или Kd. Эта утилита передает любые указанные параметры командной строки выбранному вами отладчику. По умолчанию LiveKd запускает отладчик Kd. Для запуска GUI-отлад-
   чика (Windbg), задайте ключ -w.Чтобы получить подсказку по ключам Live-Kd, укажите ключ -?.
   LiveKd предоставляет отладчику смоделированный файл аварийного дампа (crash dump), поэтому вы можете выполнять в LiveKd любые операции, поддерживаемые для аварийных дампов. Поскольку LiveKd хранит смоделированный дамп в физической памяти, отладчик ядра может попасть в такую ситуацию, в которой структуры данных находятся в рассогласованном состоянии в процессе их изменения системой. При каждом запуске отладчик получает снимок состояния системы; если вы хотите обновить этот снимок, выйдите из отладчика (командой q),и LiveKd спросит вас, нужно ли начать сначала. Если отладчик, выводя информацию на экран, вошел в цикл, нажмите клавиши Ctrl+C, чтобы прервать вывод, выйдите из отладчика и запустите его снова. Если он завис, нажмите клавиши Ctrl+Break, которые заставят завершить процесс отладчика. После этого вам будет предложено снова запустить отладчик.
 
SoftlCE
 
   Еще один инструмент, не требующий двух машин для прямой отладки ядра, - SoftICE, который можно приобрести у Compuware NuMega ( wwtv.com- puware.com ).SoftICE обладает во многом теми же возможностями, что и Windows Debugging Tools, но поддерживает переход между кодом пользовательского режима и режима ядра. Он также поддерживает DLL-модули расширения ядра Microsoft, поэтому большинство команд, описываемых нами в книге, будут работать и в SoftICE. Ha рис. 1-8 показан пользовательский интерфейс SoftICE, появляющийся при нажатии клавиши активизации SoftICE (по умолчанию - Ctrl+D); этот интерфейс представляет собой окно на рабочем столе системы, в которой он выполняется.
 
Platform Software Development Kit (SDK)
 
   Platform SDK является частью подписки на MSDN уровня Professional и выше; кроме того, его можно бесплатно скачать с msdn.microsoft.com .B нем содержатся документация, заголовочные файлы и библиотеки С, необходимые для компиляции и компоновки Windows-приложений. (Microsoft Visual C++ тоже поставляется с этими файлами, но их версии в Platform SDK всегда более новые и соответствуют самым последним версиям операционных систем Windows.) B Platform SDK для нас будут представлять интерес заголовочные файлы Windows API (\Program Files\Microsoft SDK\Include) и несколько утилит (Pfmon.exe, Pstat.exe, Pview.exe, Vadump.exe и Winobj.exe). Некоторые из них также поставляются с Ресурсами Windows и Support Tools. Наконец, отдельные утилиты поставляются с Platform SDK и MSDN Library как примеры исходного кода.
 
Device Driver Kit (DDK)
 
   Windows DDK является частью подписки на MSDN уровня Professional и выше, но в отличие от Platform SDK его нельзя скачать бесплатно (впрочем, можно заказать CD-ROM за минимальную цену). Документация Windows DDK включается в MSDN Library.
   Хотя DDK нацелен на разработчиков драйверов устройств, он представляет собой богатый источник информации о внутреннем устройстве Windows. Например, в главе 9 мы даем описание архитектуры подсистемы ввода-вывода, модели драйверов и структур данных базовых драйверов устройств, но не вдаемся в детали соответствующих функций ядра. A в документации Windows DDK исчерпывающе описаны все внутрисистемные функции и драйверы устройств.
   Кроме документации в DDK входят заголовочные файлы, определяющие ключевые внутренние структуры данных, константы и интерфейсы многих внутрисистемных подпрограмм (в частности, обратите внимание на файлы Ntddk.h и Wdm.h). Эти файлы очень полезны в исследовании внутренних структур данных Windows с помощью отладчика ядра, так как мы даем лишь обобщенное описание внутренних структур, а в заголовочных файлах можно найти все подробности о каждом поле таких структур. B DDK также детально поясняются некоторые структуры данных (вроде заголовков для диспетчера объектов, блоки ожидания, события, мутанты, семафоры и др.).
   Поэтому, если вы хотите поглубже покопаться в подсистеме ввода-вывода и в модели драйверов, читайте документацию DDK (особенно руководства Kernel-Mode Driver Architecture Design Guide и Reference). Еще один превосходный источник - книга Уолта Они (Walt Oney) «Programming the Microsoft Windows Driver Model, Second Edition» (Microsoft Press).
 
Утилиты Sysinternals
 
   Bo многих экспериментах мы используем свободно распространяемые утилиты, которые можно скачать с wwwjsysinternals.com .Большинство этих ути-
   лит написано Марком Руссиновичем, соавтором этой книги. K наиболее популярным утилитам относятся Process Explorer, Filemon и Regmon. Многие из этих утилит требуют установки и запуска драйверов устройств, работающих в режиме ядра, а значит, вам понадобятся полномочия администратора.
 
Резюме
 
   B этой главе вы познакомились с ключевыми техническими концепциями и терминами Windows, которые будут использоваться во всей книге. Вы также получили первое представление о многих полезных инструментах, позволяющих изучать внутренние структуры данных Windows. Теперь вы готовы вместе с нами приступить к исследованию внутреннего устройства системы. Мы начнем с общего обзора архитектуры системы и ее основных компонентов.
Г Л A B A 2 Архитектура системы
 
   Теперь, познакомившись с необходимыми терминами, понятиями и инструментами, мы можем рассмотреть задачи, которые ставились при разработке операционной системы Microsoft Windows. B этой главе описывается общая архитектура системы: ключевые компоненты, принципы их взаимодействия и контекст выполнения. Чтобы получить базовое представление о внутреннем устройстве Windows, давайте сначала обсудим требования и цели, обусловившие структуру и спецификацию этой системы.
 
Требования и цели проекта
 
   Характеристики Windows NT в 1989 году определялись следующими требованиями. Операционная система должна:
    (o)быть истинно 32-разрядной, реентерабельной, поддерживать вытесняющую многозадачность и работу с виртуальной памятью;
    (o)работать на разных аппаратных платформах;
    (o)хорошо масштабироваться в системах с симметричной мультипроцессорной обработкой;
    (o)быть распределенной вычислительной платформой, способной выступать в роли как клиента сети, так и сервера;
    (o)поддерживать большинство существующих 16-разрядных приложений
   MS-DOS и Microsoft Windows 3.1; (o)отвечать требованиям правительства к соответствию POSIX 1003.1;
    (o)отвечать требованиям правительства и промышленности к безопасности операционных систем;
    (o)обеспечивать простоту адаптации к глобальному рынку за счет поддержки Unicode.
   Для создания системы, соответствующей предъявленным требованиям, нужно было принять тысячи решений. Поэтому перед командой разработчиков Windows NT на начальном этапе проекта были поставлены следующие цели.
    (o) РасширяемостьКод должен быть написан так, чтобы системы можно было легко наращивать и модифицировать по мере изменения потребностей рынка.
    (o) ПереносимостьСистема должна работать на разных аппаратных архитектурах и обладать способностью к сравнительно легкому переносу на новые аппаратные архитектуры, если на рынке возникнет такая потребность.
    (o) Отказоустойчивость и надежностьСистема должна быть защищенной как от внутренних сбоев, так и от внешних деструктивных действий. У приложений не должно быть возможности нарушить работу операционной системы или других приложений.
    (o) СовместимостьХотя Windows NT должна расширить существующую технологию, ее пользовательский интерфейс и API должны быть совместимы с предыдущими версиями Windows и MS-DOS. Она также должна уметь взаимодействовать с другими системами вроде UNIX, OS/2 и NetWare.
    (o) ПроизводительностьC учетом ограничений, налагаемых поставленными целями, система должна быть максимально быстрой и отзывчивой независимо от аппаратной платформы.
   По мере изучения деталей внутренней структуры Windows вы увидите, насколько успешно были реализованы все эти требования и цели. Ho сначала мы рассмотрим общую модель Windows и сравним ее с другими современными операционными системами.
 
Модель операционной системы
 
   B большинстве многопользовательских операционных систем приложения отделены от собственно операционной системы: код ее ядра выполняется в привилегированном режиме процессора (называемом режимом ядра),который обеспечивает доступ к системным данным и оборудованию. Код приложений выполняется в непривилегированном режиме процессора (называемом пользовательским)с неполным набором интерфейсов, ограниченным доступом к системным данным и без прямого доступа к оборудованию. Когда программа пользовательского режима вызывает системный сервис, процессор перехватывает вызов и переключает вызывающий поток в режим ядра. По окончании работы системного сервиса операционная система переключает контекст потока обратно в пользовательский режим и продолжает его выполнение.
   Windows, как и большинство UNIX-систем, является монолитной операционной системой - в том смысле, что большая часть ее кода и драйверов использует одно и то же пространство защищенной памяти режима ядра. Это значит, что любой компонент операционной системы или драйвер устройства потенциально способен повредить данные, используемые другими компонентами операционной системы.
 
Основана ли Windows на микроядре?
 
   Хотя некоторые объявляют ее таковой, Windows не является операционной системой на основе микроядра в классическом понимании этого термина. B подобных системах основные компоненты операционной системы (диспетчеры памяти, процессов, ввода-вывода) выполняются как отдельные процессы в собственных адресных пространствах и представляют собой надстройки над примитивными сервисами микроядра. Пример современной системы с архитектурой на основе микроядра - операционная система Mach, разработанная в Carnegie MeI-lon University. Она реализует крошечное ядро, которое включает сервисы планирования потоков, передачи сообщений, виртуальной памяти и драйверов устройств. Все остальное, в том числе разнообразные API, файловые системы и поддержка сетей, работает в пользовательском режиме. Однако в коммерческих реализациях на основе микроядра Mach код файловой системы, поддержки сетей и управления памятью выполняется в режиме ядра. Причина проста: системы, построенные строго по принципу микроядра, непрактичны с коммерческой точки зрения из-за слишком низкой эффективности.
   Означает ли тот факт, что большая часть Windows работает в режиме ядра, ее меньшую надежность в сравнении с операционными системами на основе микроядра? Вовсе нет. Рассмотрим следующий сценарий. Допустим, в коде файловой системы имеется ошибка, которая время от времени приводит к краху системы. Ошибка в коде режима ядра (например, в диспетчере памяти или файловой системы) скорее всего вызовет полный крах традиционной операционной системы. B истинной операционной системе на основе микроядра подобные компоненты выполняются в пользовательском режиме, поэтому теоретически ошибка приведет лишь к завершению процесса соответствующего компонента. Ho на практике такая ошибка все равно вызовет крах системы, так как восстановление после сбоя столь критически важного процесса невозможно.
   Все эти компоненты операционной системы, конечно, полностью защищены от сбойных приложений, поскольку такие программы не имеют прямого доступа к коду и данным привилегированной части операционной системы (хотя и способны вызывать сервисы ядра). Эта защита - одна из причин, по которым Windows заслужила репутацию отказоустойчивой и стабильной операционной системы в качестве сервера приложений и платформы рабочих станций, обеспечивающей быстродействие основных системных сервисов вроде поддержки виртуальной памяти, файлового ввода-вывода, работы с сетями и доступа к общим файлам и принтерам.
   Компоненты Windows режима ядра также построены на принципах объектно-ориентированного программирования (ООП). Так, для получения информации о каком-либо компоненте они, как правило, не обращаются к его структурам данных. Вместо этого для передачи параметров, доступа к структурам данных и их изменения используются формальные интерфейсы.
   Однако, несмотря на широкое использование объектов, представляющих разделяемые системные ресурсы, Windows не является объектно-ориентированной системой в строгом понимании этого термина. Большая часть системного кода написана на C в целях переносимости и из-за широкой распространенности средств разработки на С. B этом языке нет прямой поддержки конструкций и механизмов ООП вроде динамического связывания типов данных, полиморфных функций или наследования классов.
 
Обзор архитектуры
 
   Теперь обратимся к ключевым компонентам системы, составляющим ее архитектуру. Упрощенная версия этой архитектуры показана на рис. 2-1. Учтите, что упрощенная схема не отражает всех деталей архитектуры (например, здесь не показаны уровни сетевых компонентов и различных типов драйверов устройств).
    Рис. 2-1. Упрощенная схема архитектуры Windows
   Ha рис. 2-1 прежде всего обратите внимание на линию, разделяющую те части Windows, которые выполняются в режиме ядра и в пользовательском режиме. Прямоугольники над этой линией соответствуют процессам пользовательского режима, а компоненты под ней - сервисам режима ядра. Как говорилось в главе 1, потоки пользовательского режима выполняются в защищенных адресных пространствах процессов (хотя при выполнении в режиме ядра они получают доступ к системному пространству). Таким образом, процессы поддержки системы, сервисов, приложений и подсистем окружения имеют свое адресное пространство.
   Существует четыре типа пользовательских процессов:
    (o)фиксированные процессы поддержки системы(system support processes) - например, процесс обработки входа в систему и диспетчер сеансов, не являющиеся сервисами Windows (т. е. не запускаемые диспетчером управления сервисами);
    (o) процессы сервисов(service processes) - носители Windows-сервисов вроде Task Scheduler и Spooler. Многие серверные приложения Windows, например Microsoft SQL Server и Microsoft Exchange Server, тоже включают компоненты, выполняемые как сервисы;
    (o) пользовательские приложения(user applications) - бывают шести типов: для 32-разрядной Windows, 64-разрядной Windows, 16-разрядной Windows 3.1, 16-разрядной MS-DOS, 32-разрядной POSIX и 32-разрядной OS/2;
    (o) подсистемы окружения(environment subsystems) - реализованы как часть поддержки среды операционной системы, предоставляемой пользователям и программистам. Изначально Windows NT поставлялась с тремя подсистемами окружения: Windows, POSIX и OS/2. Последняя была изъята в Windows 2000. Что касается Windows XP, то в ней исходно поставляется только подсистема Windows - улучшенная подсистема POSIX доступна как часть бесплатного продукта Services for UNIX. Обратите внимание на прямоугольник «DLL подсистем», расположенный на рис. 2-1 под прямоугольниками «процессы сервисов» и «пользовательские приложения». B Windows пользовательские приложения не могут вызывать родные сервисы операционной системы напрямую, вместо этого они работают с одной или несколькими DLL подсистем.Их назначение заключается в трансляции документированных функций в соответствующие внутренние (и обычно недокументированные) вызовы системных сервисов Windows. Трансляция может осуществляться как с помощью сообщения, посылаемого процессу подсистемы окружения, обслуживающему пользовательское приложение, так и без него.
   Windows включает следующие компоненты режима ядра.
    (o) Исполнительная система(executive) Windows, содержащая базовые сервисы операционной системы, которые обеспечивают управление памятью, процессами и потоками, защиту, ввод-вывод и взаимодействие между процессами.