Как создать процесс windows

Процессы в Windows
Страница 5. Создание и завершение процессов

Создание процессов

Создание Win32 процесса осуществляется вызовом одной из таких функций, как CreateProcess, CreateProcessAsUser (для Win NT/2000) и CreateProcessWithLogonW (начиная с Win2000) и происходит в несколько этапов:

— Открывается файл образа (EXE), который будет выполняться в процессе. Если исполняемый файл не является Win32 приложением, то ищется образ поддержки (support image) для запуска этой программы. Например, если исполняется файл с расширением .bat, запускается cmd.exe и т.п.

В WinNT/2000 для отладки программ реализовано следующее. CreateProcess, найдя исполняемый Win32 файл, ищет в SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Option раздел с именем и расширением запускаемого файла, затем ищет в нем параметр Debugger, и если строка не пуста, запускает то, что в ней написано вместо данной программы.

— Создается объект Win32 «процесс».

— Создается первичный поток (стек, контекст и объект «поток»).

— Подсистема Win32 уведомляется о создании нового процесса и потока.

— Начинается выполнение первичного потока.

— В контексте нового процесса и потока инициализируется адресное пространство (например, загружаются требуемые DLL) и начинается выполнение программы.

Завершение процессов

Процесс завершается если:

— Входная функция первичного потока возвратила управление.

— Один из потоков процесса вызвал функцию ExitProcess.

— Поток другого процесса вызвал функцию TerminateProcess.

Когда процесс завершается, все User- и GDI-объекты, созданные процессом, уничтожаются, объекты ядра закрываются (если их не использует другой процесс), адресное пространство процесса уничтожается.

Практическое руководство. Создание рабочего процесса How to: Create a Workflow

Рабочие процессы могут создаваться как из встроенных, так и из пользовательских действий. Workflows can be constructed from built-in activities as well as from custom activities. В подразделах этого раздела приводится пошаговая процедура создания рабочего процесса, который использует как встроенные действия, такие как Flowchart действие, так и пользовательские действия из предыдущего раздела Практическое руководство. Создание действия . The topics in this section step through creating a workflow that uses both built-in activities such as the Flowchart activity, and the custom activities from the previous How to: Create an Activity topic. Рабочий процесс моделирует игру по угадыванию числа. The workflow models a number guessing game. Для завершения учебника требуется только один из подразделов в этом разделе. Необходимо выбрать стиль, который вас интересует, и выполнить шаг. Only one of the topics in this section is required to complete the tutorial; you should pick the style that interests you and follow that step. Однако при необходимости можно завершить все подразделы. However, you may complete all of the topics if desired.

Каждый раздел в учебнике «Приступая к работе» построен на основе предыдущих разделов. Each topic in the Getting Started tutorial depends on the previous topics. Для выполнения этой статьи сначала необходимо выполнить действия по созданию действия. To complete this topic, you must first complete How to: Create an Activity.

Читайте также:  После загрузки windows отключается монитор

В этом разделе In This Section

Практическое руководство. Создание последовательного рабочего процесса How to: Create a Sequential Workflow
Описывает, как создать последовательный рабочий процесс с помощью действия Sequence. Describes how to create a sequential workflow using the Sequence activity.

Практическое руководство. Создание рабочего процесса c блок-схемой How to: Create a Flowchart Workflow
Описывает, как создать рабочий процесс блок-схемы с помощью действия Flowchart. Describes how to create a flowchart workflow using the Flowchart activity.

Практическое руководство. Создание рабочего процесса конечного автомата How to: Create a State Machine Workflow
Описывает способы создания рабочего процесса конечного автомата с помощью действия StateMachine. Describes how to create a state machine workflow using the StateMachine activity.

Создание процессов

Создать процесс — это прежде всего означает создать описатель процесса, в каче­стве которого выступает одна или несколько информационных структур, содержащих все сведения о процессе, необходимые ОС для управления им.

Три основные события, приводящие к созданию процессов:

− Работающий процесс подает системный вызов на создание процесса.

− Запрос пользователя на создание процесса.

Во всех случаях, активный текущий процесс посылает системный вызов на создание нового процесса.

В ОС каждому процессу присваивается идентификатор процесса ( PID — Process IDentifier)

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

Приложение тоже может создать процесс с главным потоком, используя для этой цели функцию CreateProcess(). Её прототип, находящийся в файле winbase.h, при первой встрече с ним внушает легкий ужас:

BOOL CreateProcess(LPCSTR lpApplicationName,

LPSTR lpCommandLine,

LPSECURITY_ATTRIBUTES lpProcessAttributes,

LPSECURITY_ATTRIBUTES lpThreadAttributes,

BOOL bInheritHandles,

DWORD dwCreationFlags,

LPVOID lpEnvironment,

LPCSTR lpCurrentDirectory,

LPSTARTUPINFO lpStartupInfo,

LPPROCESS_INFORMATION lpProcessInformation);

Возвращаемое значение. В начале работы функция выделяет память для этой структуры, а потом выделяет память (виртуальную, естественно) для адресного пространства процесса. Если выделение памяти прошло без ошибок, в адресное про­странство процесса загружается код исполняемой программы и исполь­зуемых программой динамических библиотек. Только после этого созда­ется главный поток процесса. Если функции удастся произвести все эти действия без ошибок, то возвращаемое значение будет равно TRUE. FALSE явится индикатором того, что по каким-то причинам процесс не создан.

Первый аргумент — lpApplicationName — определяет имя исполняемого файла, для которого создается процесс. Если имя файла приводится без расширения, предполагается расширение *.exe, которое присоединяется к имени файла. Если же имя файла завершается точкой (.), тогда расширение *.exe к нему не присоединяется. Поиск файла исполняемой программы осуществляется Windows в следующем порядке.

1. В каталоге, в который загружено приложение.

2. В текущем каталоге.

3. В системном каталоге Windows.

4. В каталоге Windows, который возвращает функция GetWindowDirectory().

5. В каталогах, перечисленных в переменной окружения PATH, которая определяет порядок поиска в них.

Второй аргумент — lpCommandLine определяет передаваемую этому файлу командную строку. Если lpApplicationName равен NULL, то пер­вый (до первого пробела) элемент lpCommandLine считается именем исполняемого файла.

Читайте также:  Не работает клавиатура windows bootcamp

Третий и четвертый аргументы – lpProcessAttributes, lpThreadAttributes — определяют атрибуты защиты к про­цессу и потоку соответственно. В Windows 9х эти значения равны NULL.

Пятое поле – bInheritHandles – устанавливает разрешение/запрет наследования хэндлов вызывающего процесса, если установлено значение TRUE. При этом новый процесс наследует каждый наследуемый хэндл, открытый в вызывающем процессе. У наследуемых хэндлах имеются те же значения и привилегии, что и у исходных дискрипторов.

Шестое поле — dwCreationFlag — является комбинацией битовых флагов, управляющих созданием процесса и назначением для него приоритета. Этот параметр позволяет установить класс приоритета для объекта процесса наряду с режимами его выполнения. Существует две группы флагов:

— флаги создания процесса;

— флаги установки уровня приоритета.

Седьмой аргумент — lpEnvironment – указатель на настройки окружения нового процесса. Это перечень выражений присвоения в виде переменная=значение, завершающихся нулевым символом. Обычно равен NULL. Это означает, что порождаемый процесс наследует переменные окружения родительского процесса. Если этот аргумент не равен NULL, то он должен содержать указатель на блок памяти, содер­жащий те переменные окружения, которыми будет пользоваться порож­даемый процесс.

Восьмой аргумент функции — lpCurrentDirectory – указатель на строку, содержащую текущие диск и директорию для порождаемого процесса. Если этот аргумент равен NULL, порождаемый процесс наследует текущие диск и директорию родительского процесса. В противном случае этот аргумент должен указывать на строку, в которой указан полный путь к устанавливаемой текущей директории, включающий и букву дисковода.

Девятый аргумент – lpStartupInfo — указатель на структуру типа STARTUPINFO, которая описывает способ отображения основного окна приложения.

Десятый аргумент функции CreateProcess() — lpProcessInformation — указывающий на структуру типа PROCESS_INFORMATION, в которую записывается информация о порожденном процессе после его создания. Эта структура описана содержит хэндл созданного про­цесса, хэндл потока, уникальные идентификаторы процесса и потока.

Следует особое внимание на последние два поля. Дело в том, что Win32, если идентификатор освобожден, может повторно использовать его. К примеру, пусть процессу присвоен идентификатор 0x00001111. После завершения процесса идентификатор освобождается и какому-нибудь новому процессу может опять быть присвоен тот же идентификатор 0x00001111. Это необходимо учитывать при написании программ.

Процессы Windows

Понятие «процесса» существовало в операционных системах Windows задолго до появления платформы .NET. Попросту говоря, под процессом понимается выполняющаяся программа. Однако формально — это концепция уровня операционной системы, которая используется для описания набора ресурсов (таких как внешние библиотеки кода и главный поток) и необходимой памяти, используемой выполняющимся приложением. Для каждого загружаемого в память файла *.ехе в операционной системе создается отдельный изолированный процесс, который используется на протяжении всего времени его существования. Благодаря такой изоляции приложений, исполняющая среда получается гораздо более надежной и стабильной, поскольку выход из строя одного процесса никак не сказывается на работе других процессов.

Более того, доступ напрямую к данным в одном процессе из другого процесса невозможен, если только не применяется API-интерфейс распределенных вычислений, такой как Windows Communication Foundation. Из-за всех этих моментов процесс может считаться фиксированной и безопасной границей выполняющегося приложения.

Каждый процесс Windows получает уникальный идентификатор процесса (Process ID — PID) и может независимо загружаться и выгружаться операционной системой (в том числе программно). Как уже наверняка известно, в окне WindowsTask Manager (Диспетчер задач) имеется вкладка Processes (Процессы), на которой можно просматривать различные статические данные о выполняющихся на данной машине процессах, в том числе их PID-идентификаторы и имена образов. Чтобы открыть окно диспетчера задач, нажмите комбинацию клавиш :

Читайте также:  Восстановление ноутбука asus до заводских настроек windows

Роль потоков

В каждом процессе Windows содержится первоначальный «поток», который является входной точкой для приложения. Потоком называется используемый внутри процесса путь выполнения. Формально поток, который создается первым во входной точке процесса, называется главным потоком (primary thread). В любой исполняемой программе .NET (консольном приложении, приложении Windows Forms, приложении WPF и т.д.) входная точка обозначается как метод Main(). При вызове этого метода главный поток создается автоматически.

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

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

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

Однако такого может и не происходить: в случае использования слишком большого количества потоков в одном процессе его производительность может даже ухудшаться из-за возникновения у ЦП необходимости переключаться между активными потоками в процессе (что отнимает определенное время).

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

Чтобы поток не забывал, на чем он работал перед тем, как его выполнение было приостановлено, каждому потоку предоставляется возможность записывать данные в и выделяется отдельный стек вызовов, как показано на рисунке:

Оцените статью