Файл: Руссинович М., Маргозис А. Утилиты Sysinternals. Справочник администратора 2012.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Операционные системы

Добавлен: 29.10.2018

Просмотров: 33026

Скачиваний: 742

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

22  Часть 

I   

Приступая к работе

процессов как единым целым. Например, задание может использоваться 
для одновременного завершения группы процессов вместо поочередного за-
вершения, при этом вызывающему процессу не важно, какие процессы на-
ходятся в группе. Кроме того, объект-задание позволяет управлять опреде-
ленными атрибутами и создает ограничения для процесса или процессов, 
связанных с заданием. В частности, задания могут налагать ограничения по 
времени выполнения в пользовательском режиме и переданной виртуаль-
ной памяти для каждого процесса или задания в целом. Инструментарий 
управления Windows
 (WMI) загружает свои провайдеры в отдельные хост-
процессы, управляемые заданием, которое ограничивает потребление па-
мяти, а также общее количество хост-процессов провайдера WMI, которые 
могут работать одновременно.

Как сказано выше, процесс — это всего лишь контейнер. С технической 

точки зрения выполняются не процессы, а содержащиеся в них потоки. 
Поток — это объект внутри процесса, который Windows может планировать 
и выполнить. Он включает в себя следующие основные компоненты:
•  Содержимое регистров центрального процессора, т.е. состояние процес-

сора. Оно включает указатель, идентифицирующий следующий машин-
ный код, который будет выполнен потоком.

•  Два стека — для режима ядра и режима пользователя.
•  Закрытая область памяти, которая называется локальной памятью пото-

ка (TLS). Она предназначена для использования подсистемами, библио-
теками исполняющей системы и динамически подключаемыми библио-
теками (DLL).

•  Уникальный идентификатор, который называется идентификатором по-

тока (TID). Идентификаторы процессов и потоков генерируются в одном 
пространстве имен, поэтому они никогда не перекрываются.

•  Иногда потоки имеют собственный контекст безопасности, например в 

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

все потоки внутри процесса сообща используют его виртуальное адресное 
пространство (и остальные ресурсы, принадлежащие процессу). Это озна-
чает, что все потоки процесса могут читать и записывать память друг друга. 
Потоки, однако, не могут ссылаться на адресное пространство другого про-
цесса, пока другой процесс не откроет часть своего закрытого адресного про-
странства в виде общего раздела (в Windows API это называется объектом 
«проекция файла») или пока один процесс не получит право открыть другой 
процесс для вызова межпроцессных функций для работы с памятью.

По умолчанию потоки не имеют собственного маркера доступа, однако 

могут приобрести его. Так отдельным потокам удается олицетворять кон-
текст безопасности, отличный от контекста остальных потоков данного про-
цесса, например, на удаленных Windows-системах, не влияя на другие по-
токи «своего» процесса.

SIN_ch_02.indd   22

27.12.2011   14:12:05


background image

Основные понятия Windows  

Глава 2  23 

Пользовательский режим и режим ядра

Для предотвращения доступа к важнейшим данным операционной системы 
и их модификации пользовательскими приложениями Windows исполь-
зует два режима доступа к процессору: пользовательский режим и режим 
ядра. Все процессы, кроме системных, работают в пользовательском режиме 
(«кольцо 3» в терминах архитектуры Intel x86 и x64), в то время как драйве-
ры устройств и компоненты операционной системы, в частности, исполни-
тельная система и ядро, работают только в режиме ядра. Режим ядра соот-
ветствует т.н. «кольцо 0» процессоров x86 и x64, поэтому в данном режиме 
доступна вся память системы и все команды процессора. Разрешая только 
низкоуровневым компонентам операционной системы с более высоким 
уровнем привилегий, чем у процессов пользовательского режима, процес-
сор предоставляет разработчикам операционных систем необходимые им 
возможности, не позволяя приложениям, содержащим ошибки, нарушать 
стабильность системы в целом.

 Примечание 

Не путайте различие между пользовательским режимом и режимом 

ядра с различием между правами пользователя и правами администратора. В данном 
контексте «пользовательский режим» не означает «режим с правами обычного поль-
зователя».

Несмотря на то, что каждый процесс Windows имеет собственное закры-

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

Потоки процессов пользовательского режима переключаются в режим 

ядра при вызове системных служб. Например, вызов API-функции Windows 
ReadFile в конечном итоге должен вызвать внутреннюю функцию Windows, 
фактически осуществляющую чтение данных из файла. Так как эта функ-
ция имеет доступ к внутренним структурам данных системы, она должна 
работать в режиме ядра. Переход из пользовательского режима в режим 
ядра выполняется с помощью специальной команды процессора, которая 
переводит процессор в режим исполнения системных функций в режиме 
ядра. Операционная система выполняет соответствующую внутреннюю 
функцию, которой, в случае с ReadFile, является функция ядра NtReadFile
Служебные функции ядра проверяют параметры и выполняют соответ-
ствующие проверки прав доступа с помощью Монитора защиты (Security 
Reference Monitor) перед тем как выполнить запрашиваемую операцию. 
После завершения функции операционная система переключает процессор 
обратно в пользовательский режим.

SIN_ch_02.indd   23

27.12.2011   14:12:05


background image

24  Часть 

I   

Приступая к работе

Таким образом, для потоков из процессов пользовательского режима ха-

рактерна попеременная работа в пользовательском режиме и в режиме ядра. 
Более того, вследствие того, что большинство кода графической и оконной 
подсистем работает в режиме ядра, процессы приложений, интенсивно ис-
пользующих графику, могут проводить больше времени в режиме ядра, чем 
в пользовательском режиме. Посмотреть эти два режима можно на графике 
использования центрального процессора программы Process Explorer: крас-
ная часть графика обозначает время, проведенное в режиме ядра, а зеленая 
часть графика — время, проведенное в пользовательском режиме.

Описатели

Код ядра Windows, содержащийся в файле в Ntoskrnl.exe и работающий, 
естественно, в режиме ядра, состоит из ряда подсистем, таких как диспетчер 
памяти (Memory Manager), диспетчер процессов (Process Manager), диспет-
чер ввода-вывода (I/O Manager) и диспетчер конфигураций (Configuration 
Manager) (реестр), являющихся компонентами исполняющей системы. 
Каждая из этих подсистем определяет с помощью диспетчера объектов 
один или несколько типов для ресурсов, предоставляемых приложениям. 
Например, Диспетчер конфигураций (Configuration Manager) определяет 
объект раздел (Key) для представления открытого раздела  реестра; диспет-
чер памяти (Memory Manager) определяет объект-раздел (Section), пред-
ставляющий общую память; исполняющая подсистема  определяет такие 
объекты, как семаформутант (таково внутрисистемное имя мьютекса) и 
синхронизирующие объекты-события (объекты-оболочки базовых струк-
тур данных, определяемых подсистемой ядра операционной системы). 
Диспетчер ввода-вывода определяет объект файл (File) для представления 
открытых экземпляров ресурсов драйверов устройств, включающих файлы 
файловой системы; а диспетчер процессов создает объекты поток (Thread) и 
процесс (Process). В каждой версии Windows добавляются новые типы объ-
ектов, например, в Windows 7 таковых 42. Типы объектов в той или иной 
версии Windows, можно посмотреть, запустив утилиту WinObj (см. главу 
14) с правами администратора и перейдя в каталог ObjectTypes в простран-
стве имен диспетчера объектов.

Если приложение захочет использовать один из этих ресурсов, оно долж-

но сначала вызвать соответствующую API-функцию, чтобы создать или от-
крыть ресурс. Например, функция CreateFile  открывает или создает файл, 
функция  RegOpenKeyEx  открывает раздел реестра, а CreateSemaphoreEx 
открывает или создает семафор. Если функция выполняется успешно, 
Windows создает ссылку на объект в таблице описателей, которая ведется 
исполняющей системой, и возвращает приложению индекс новой записи в 
таблице описателей.

Описатель нужен приложению для выполнения над ресурсом различ-

ных операций. Для обращения к ресурсам и управления ими приложение 

SIN_ch_02.indd   24

27.12.2011   14:12:05


background image

Основные понятия Windows  

Глава 2  25 

передает значение описателя API-функциям, таким как ReadFile, SetEvent, 
SetThreadPriority 
и MapViewOfFile. Чтобы найти объект, на который ссыла-
ется описатель, система просматривает с использованием индекса таблицу 
описателей в поисках записи, содержащей указатель на объект. В этой за-
писи также хранятся сведения о правах доступа процесса, открывшего объ-
ект, что позволяет системе пресекать выполнение процессом несанкциони-
рованных операций над объектом. Например, если процесс успешно открыл 
файл для чтения и попытался использовать тот же описатель для записи, 
соответствующий вызов завершится неудачей.

Когда объект становится ненужным процессу, последний освобождает 

свой описатель этого объекта. Обычно это делается путем передачи значе-
ния описателя API-функции CloseHandle. (Обратите внимание на то, что не-
которые диспетчеры ресурсов поддерживают иные функции освобождения 
ресурсов). После завершения процесса все принадлежащие ему описатели 
закрываются.

Стеки вызовов и символы

Некоторые утилиты Sysinternals, включая Process Explorer, Process Monitor 
и VMMap, могут отображать сведения об исполняемом в различные момен-
ты коде, т.е. содержимое стеков вызовов. Привязка символов к модулям в 
адресном пространстве процесса позволяет получить больше понятной че-
ловеку контекстной информации об исполняемом коде, особенно системном 
коде Windows. Если вы разберетесь со стеками вызовов и символами, а так-
же их настройкой в утилитах Sysinternals, вам будет намного проще изучать 
поведение процессов и отыскивать первопричины проблем.

Что такое стек вызовов?

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

На рис. 2-4 показан вымышленный пример такой ситуации. Программа 

MyApp.exe поставляется с библиотекой HelperFunctions.dll. Эта DLL со-
держит функцию EncryptThisText, которая шифрует передаваемый ей текст. 
После выполнения ряда подготовительных операций EncryptThisText вызы-
вает API-функцию Windows CryptEncryptMessage в Crypt32.dll. В какой-то 
момент CryptEncryptMessage нужно некоторое количество памяти, и она вы-
зывает функцию выделения памяти malloc из Msvcrt.dll. После того как malloc 
выполнила свою работу и зарезервировала необходимое количество памяти, 
управление возвращается функции CryptEncryptMessage. Когда завершится 
и  CryptEncryptMessage, управление возвращается функции EncryptThisText, 
вернее, ее команде, следующей сразу после вызова CryptEncryptMessage.

SIN_ch_02.indd   25

27.12.2011   14:12:05


background image

26  Часть 

I   

Приступая к работе

MyApp.exe

HelperFunctions.dll

Crypt32.dll

Msvcrt.dll

EncryptThisText()

CryptEncrtypMessage()

malloc()

Виртуальное адресное пространство процесса

Рис. 2-4.  Пример последовательных вызовов

Благодаря стеку вызовов система «знает», какой функции следует возвра-

щать управление после завершения последовательно вызванных функций, 
как передавать параметры от одной функции к другой и как хранить пере-
менные локальных функций. Стек вызовов работает по принципу «первым 
вошел, последним вышел», т.е. элементы стека после завершения функций 
удаляются в порядке, обратном их добавлению при вызовах. Когда функция 
собирается вызвать другую функцию, она записывает адрес в памяти сле-
дующей команды, т.е. команды, которая будет выполняться при завершении 
вызываемой функции (т.н. «адрес возврата») в верхнюю часть стека. Если 
вызванная функция, в свою очередь, вызывает третью функцию, та тоже за-
пишет в стек свой адрес возврата. При завершении функции система читает 
адрес из первого элемента стека и продолжает выполнять код с места, на ко-
торое указывает этот адрес.

Элементы стека вызовов формируются по шаблону имя_модуля!имя_

функции+смещение, где имя_модуля — это имя исполняемого файла, содер-
жащего функцию, а смещение — это число (в шестнадцатеричной системе 
счисления) байтов перед началом функции. Если имя функции недоступно, 
адрес отображается просто как имя_модуля+смещение. В показанном выше 
примере с malloc стек вызовов может выглядеть следующим образом:

msvc rt!malloc+0x2a

crypt32!CryptEncryptMessage+0x9f
Helper Functions !EncryptThisText+0x43
MyApp.exe+0x25d8

В стеке видно, какой код исполняется, и какой путь прошла программа, 

чтобы запустить его.

Что такое символы?

При проверке начального адреса или адреса возврата потока отладчику лег-
ко определить, к какому модулю он принадлежит, просмотрев список за-

SIN_ch_02.indd   26

27.12.2011   14:12:05