Наверх Системное программирование
Предыдущий раздел Оглавление Следующий раздел

ЛАБОРАТОРНАЯ РАБОТА № 4

Процессы

Цель работы: Получение практических навыков при использовании Win32 API для исследования процессов

Методические указания к выполнению лабораторной работы

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

  1. виртуальное адресное пространство;
  2. системные ресурсы, такие как растровые изображения, файлы, области памяти и т.д.;
  3. модули процесса, то есть исполняемые модули, которые отображены (загружены) в его адресное пространство;
  4. уникальный идентификационный номер, называемый идентификатором процесса;
  5. один или несколько потоков управления.

Поток – это внутренняя составляющая процесса, которой операционная система выделяет процессорное время. Каждый процесс должен иметь, по крайней мере, один поток. Поток включает:

  1. текущее состояние регистров процессора;
  2. два стека, один из которых используется при выполнении в режиме ядра, второй - при выполнении в пользовательском режиме;
  3. участок памяти для работы подсистем, библиотеки времени выполнения;
  4. динамические библиотеки;
  5. уникальный идентификатор, называемый идентификатором потока.

Состояние регистров, содержимое стека и области памяти называют контекстом потока (thread's context).

Основное назначение потоков – дать процессу возможность поддерживать несколько ветвей управления, то есть выполнять больше задач одновременно.

Дескрипторы и идентификаторы процессов

Дескриптор процесса определяется функцией CreateProcess (подробнее см. [1]), идентификатор текущего процесса – функцией GetCurrentProcessId. Чтобы определить идентификатор другого процесса, необходимо получить список всех процессов и выбрать из него тот процесс, характеристики которого требуются или воспользоваться или воспользовать методикой получения идентификатора процесса от окна ([1], с. 42).

Между дескриптором и идентификатором процесса (или потока) существуют следующие основные различия:

  1. дескриптор действует в пределах своего процесса, в то время как идентификатор работает на системном уровне. Таким образом, дескриптор действует только в пределах того процесса, в котором он был создан;
  2. у каждого процесса только один идентификатор, но может быть несколько дескрипторов;
  3. некоторым API-функциям требуется идентификатор, в то время как другим – дескриптор процесса.

Идентификация процесса

Идентификация процесса возможна различными способами с использованием следующих объектов:

  1. идентификатор процесса;
  2. дескриптор процесса;
  3. полное имя загрузочного файла;
  4. дескриптор модуля загрузочного файла процесса.

Имена файлов и дескрипторы модулей

Каждый модуль (DLL, OCX, DRV и т.д.), загруженный в пространство процесса, имеет свой дескриптор (module handle), называемый также логическим номером экземпляра (instance handle). В 16-разрядной Windows данными терминами обозначались разные объекты, в 32-разрядной системе это один и тот же объект.

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

Перейти от имени файла модуля к дескриптору модуля и наоборот не составляет особого труда, по крайней мере, в пределах одного процесса. Функция GetModuleFileName принимает дескриптор модуля, чтобы вернуть полное имя (имя и путь) исполняемого файла.

Псевдодескрипторы процессов

Функция GetСurrentProcess возвращает псевдодескриптор текущего процесса.

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

Хотя назначение псевдодескрипторов и обычных дескрипторов почти одно и то же, у них все же есть некоторые существенные различия. Псевдодескрипторы не могут наследоваться порожденными процессами, как настоящие дескрипторы (real handler). К тому же псевдодескрипторы ссылаются только на текущий процесс, а настоящие дескрипторы могут ссылаться и на внешний (foreign).

Windows предоставляет возможность получения настоящего дескриптора по псевдодескриптору при помощи API-функции DuplicateHandle.

Перечисление процессов в Windows 9x. Моментальные снимки

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

В этой динамической среде имело бы смысл на мгновение заморозить систему, чтобы получить такую системную информацию. В ТооlНе1р32 не предусмотрено средств замораживания системы, но есть функция, с помощью которой можно сделать "снимок" системы в заданный момент времени – CreateToolhelp32Snapshot().

Задание для выполнения лабораторной работы

Составить следующую программу, которая:

  • принимая дескриптор, имя или полное имя модуля, возвращает другие два элемента в своих выходных параметрах (выполнить задание для своей программы и для любой известной библиотеки)
  • будет выполнять последовательно по шагам следующее:
    1. Используя функцию GetCurrentProcessId определит идентификатор текущего процесса.
    2. Используя функцию GetCurrentProcess определит псевдодескриптор текущего процесса.
    3. Используя функцию DuplicateHandle и значение псевдодескриптора определит дескриптора текущего процесса.
    4. Используя функцию OpenProcess определит копию дескриптора текущего процесса
    5. Закроет дескриптор, полученный функцией DuplicateHandle
    6. Закроет дескриптор, полученный функцией OpenProcess
  • выдает список перечисления всех процессов, потоков, модулей и их свойства в системе.

Видео выполнения работы

Ход выполнения лабораторной работы

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

  1. Создать форму с элементами для вывода информации о занятой памяти;
  2. Сделать снимок памяти функцией CreateToolhelp32Snapshot, первый параметр будет TH32CS_SNAPPROCESS, который указывает, что нам нужен снимок именно процессов;
  3. С помощью функции Process32First и Process32Next занести информацию о процессе в структуру, а из структуры, соответственно, в таблицу;
  4. Получить дескриптор процесса с помощью функции OpenProcess по его ID;
  5. Используя функцию GetProcessMemoryInfo, получить информацию об используемой памяти выбранного процесса, которую также следует занести в таблицу.

Вывод информации о потоках выбранного процесса

  1. Сделать снимок памяти функцией CreateToolhelp32Snapshot, первый параметр будет TH32CS_SNAPTHREAD, который указывает, что нам нужен снимок потоков;
  2. С помощью функций Thread32First и Thread32Next занести информацию о процессе в структуру, а из структуры, соответственно, в таблицу;
  3. В конце работы закрыть все открытые дескрипторы;
  4. С помощью функции GetCurrentProcessId определить ID текущего процесса;
  5. С помощью функции GetCurrentProcess определить псевдодескриптор;
  6. С помощью функции DuplicateHandle определить дескриптор текущего процесса;
  7. С помощью функции OpenProcess определить дескриптор текущего процесса.

Вывод информации о модулях текущего процесса

  1. С помощью функции GetModuleFileName можно узнать модель текущего процесса;
  2. С помощью имени модуля определяем его дескриптор с функцией GetModuleHandle.

Вывод информации о модулях всех процессов

  1. Сделать снимок памяти функцией CreateToolhelp32Snapshot, первый параметр будет TH32CS_SNAPMODULE, который указывает, что снимок будет именно процессов;
  2. Функции module32First и module32Next позволяют занести всю информацию о процессе в структуру, а из структуры, соответственно, в таблицу;
  3. Закрыть все открытые дескрипторы.
Предыдущий раздел Оглавление Следующий раздел