Внутреннее устройство потоков

Теперь, изучив анатомию процессов, рассмотрим структуру потоков. Там, где явно не сказано обратное, считайте, что весь материал этого раздела в равной мере относится как к обычным потокам пользовательского режима, так и к системным потокам режима ядра (описанным в главе 3).

Структуры данных

Ha уровне операционной системы поток представляется блоком потока, принадлежащим исполнительной системе (ETHREAD). Структура этого блока показана на рис. 6–7. Блок ETHREAD и все структуры данных, на которые он ссылается, существуют в системном адресном пространстве, кроме блока переменных окружения потока (thread environment block, TEB) — он размещается в адресном пространстве процесса. Помимо этого, процесс подсистемы Windows (Csrss) поддерживает параллельную структуру для каждого потока, созданного в Windows-процессе. Часть подсистемы Windows, работающая в режиме ядра (Win32k.sys), также поддерживает для каждого потока, вызывавшего USER- или GDI-функцию, структуру W32THREAD, на которую указывает блок ETHREAD.

2.Внутреннее устройство Windows (гл. 5-7) pic_40.png

Поля блока потока, показанные на рис. 6–7, в большинстве своем не требуют дополнительных пояснений. Первое поле — это блок потока ядра (KTHREAD). За ним следуют идентификационные данные потока и процесса (включая указатель на процесс — владелец данного потока, что обеспечивает доступ к информации о его окружении), затем информация о защите в виде указателя на маркер доступа и сведения, необходимые для олицетворения (подмены одного процесса другим), а также поля, связанные с сообщениями LPC и незавершенными запросами на ввод-вывод. B таблице 6–8 даны ссылки на другие части книги, где некоторые из наиболее важных полей описываются подробнее. Чтобы получить более детальные сведения о внутренней структуре блока ETHREAD, используйте команду dt отладчика ядра.

2.Внутреннее устройство Windows (гл. 5-7) pic_41.png

Давайте повнимательнее присмотримся к двум ключевым структурам потока, упомянутым выше, — к блокам KTHREAD и TEB. Первый содержит информацию, нужную ядру Windows для планирования потоков и их синхронизации с другими потоками. Схема блока KTHREAD показана на рис. 6–8.

2.Внутреннее устройство Windows (гл. 5-7) pic_42.png

Ключевые поля блока KTHREAD кратко рассмотрены в таблице 6–9.

Таблица 6–9. Ключевые поля блока KTHREAD

2.Внутреннее устройство Windows (гл. 5-7) pic_43.png
2.Внутреннее устройство Windows (гл. 5-7) pic_44.png

ЭКСПЕРИМЕНТ: просмотр структур ETHREAD и KTHREAD

Структуры ETHREAD и KTHREAD можно просмотреть с помощью команды dt отладчика ядра. B следующем выводе показан формат ETHREAD:

2.Внутреннее устройство Windows (гл. 5-7) pic_45.png
2.Внутреннее устройство Windows (гл. 5-7) pic_46.png

Для просмотра KTHREAD предназначена аналогичная команда:

2.Внутреннее устройство Windows (гл. 5-7) pic_47.png
2.Внутреннее устройство Windows (гл. 5-7) pic_48.png

ЭКСПЕРИМЕНТ: использование команды !thread отладчика ядра

Команда !thread отладчика ядра выдает дамп подмножества информации из структур данных потока. Отладчик ядра выводит ряд важных данных, не показываемых любыми другими утилитами: адреса внутренних структур, детальные сведения о приоритетах, данные стека, список незавершенных запросов на ввод-вывод и список ожидаемых объектов для тех потоков, которые находятся в состоянии ожидания.

Чтобы получить информацию о потоке, используйте либо команду !process (которая выводит все блоки потоков после блока процесса), либо команду !thread (которая сообщает сведения только об указанном потоке). Ниже дан пример информации о потоке с пояснением ее важнейших полей.

Адрес Идентификатор ETHREAD потока Адрес TEB
2.Внутреннее устройство Windows (гл. 5-7) pic_49.png

ЭКСПЕРИМЕНТ: просмотр информации о потоке

Утилита Tlist из Windows Debugging Tools позволяет получить подробную информацию о процессе, пример которой приведен ниже. Заметьте, что в списке потоков указывается «Win32StartAddress». Это адрес, передаваемый функции CreateThread приложением. Остальные утилиты, кроме Process Explorer, показывающие стартовый адрес потока, выводят его истинный стартовый адрес, а не стартовый адрес, заданный приложением.

2.Внутреннее устройство Windows (гл. 5-7) pic_50.png

B отличие от других структур данных, описываемых в этом разделе, только блок TEB, показанный на рис. 6–9, присутствует в адресном пространстве процесса, а не системы. B TEB хранится контекстная информация загрузчика образов и различных Windows DLL. Поскольку эти компоненты выполняются в пользовательском режиме, им нужны структуры данных, доступные для записи из этого режима. Вот почему TEB размещается в адресном пространстве процесса, а не системы, где он был бы доступен для записи только из режима ядра. Адрес TEB можно найти с помощью команды !thread отладчика ядра.

2.Внутреннее устройство Windows (гл. 5-7) pic_51.png

ЭКСПЕРИМЕНТ: исследуем TEB

Вы можете получить дамп структуры TEB, используя команду !teb отладчика ядра. Ee вывод выглядит так:

2.Внутреннее устройство Windows (гл. 5-7) pic_52.png
Переменные ядра

Как и в случае процессов, ряд переменных ядра Windows контролирует выполнение потоков. Список таких переменных, связанных с потоками, приводится в таблице 6-10.

Таблица 6-10. Переменные ядра, относящиеся к потокам

2.Внутреннее устройство Windows (гл. 5-7) pic_53.png
Счетчики производительности

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

2.Внутреннее устройство Windows (гл. 5-7) pic_54.png
Сопутствующие функции

B таблице 6-12 перечислены Windows-функции, позволяющие создавать потоки и манипулировать ими. Здесь не показаны функции, связанные с планированием и управлением приоритетами потоков, — они описываются в разделе «Планирование потоков» далее в этой главе.

2.Внутреннее устройство Windows (гл. 5-7) pic_55.png
Рождение потока

Жизненный цикл потока начинается при его создании программой. Запрос на его создание в конечном счете поступает исполнительной системе Windows, где диспетчер процессов выделяет память для объекта «поток» и вызывает ядро для инициализации блока потока ядра. Ниже перечислены основные этапы создания потока Windows-функцией CreateThread (которая находится в Kernel32.dll).

1. CreateThread создает стек пользовательского режима в адресном пространстве процесса.

2. CreateThread инициализирует аппаратный контекст потока, специфичный для конкретной архитектуры процессора. (Подробнее о блоке контекста потока см. раздел справочной документации Windows API по структуре CONTEXT.)

3. Для создания объекта «поток» исполнительной системы вызывается Nt-CreateThread. Он создается в приостановленном состоянии. Описание операций, выполняемых NtCreateThread, см. в разделе «Что делает функция CreateProcess» (этапы 3 и 6) ранее в этой главе.


Перейти на страницу:
Изменить размер шрифта: