Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
шпора 97.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
778.75 Кб
Скачать

2.4 Определение исполняемого образа и командной строки

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

• Если значение параметра lpszImageName не NULL, то это имя исполняемого файла. В случае если оно содержит пробелы, можно использовать кавычки.

• В противном случае имя исполняемого файла — первый элемент параметра lpszCortmandLine.

Обычно указывают только параметр lpszComanandLine, присваивая параметру lpszImageName значение NULL. Тем не менее существуют подробные правила для параметра lpszImageName.

• Если параметр lpszImageName имеет значение не NULL то он указывает имя загрузочного файла. Указывайте полный путь и имя файла. Можете указать только имя файла, тогда будут использованы текущие диск и каталог без допол­нительного поиска. В имя файла включайте его расширение ( . ЕХЕ, . ВАТ и т.п.).

• Если параметр lpszImageName имеет значение NULL то за имя программы принимается первый элемент параметра lpszCommandLine, отделенный пробе­лом. Если это имя не содержит полного пути, происходит поиск в определенной последовательности.

1. Каталог образа текущего процесса.

2. Текущий каталог.

3. Системный каталог Windows, полученный посредством вызова функции

4. Каталог Windows, полученный посредством вызова функции

5. Каталоги, указанные в переменной окружения РАТН.

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

Отметим, что командная строка не является константой. Это следует из того факта, что параметры argv для главной программы тоже не константы. Программа может изменять свои параметры, поэтому желательно делать изменения в копии строки параметров.

Не требуется создавать новый процесс с таким же определением переменной препро­цессора UNICODE, что и родительский. Возможны все комбинации. Для разработки пере­носимого кода полезно использовать макрос _tmain.

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

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

HANDLE GetCurrentProcess (VOID)

DWORD GetCurrentProcessId (VOID)

Функция GetCurrentProcess в действительности возвращает псевдодескриптор, который не может быть унаследован. Это значение используется в случаях, когда про­цессу требуется собственный дескриптор. Создавайте настоящий дескриптор процесса из его ID, используя в вызове функции OpenProcess значение, возвращенное функ­цией GetCurrentProcessId.

HANDLE OpenProcess ( DWORD fdwAccess, BOOL fInherit,

DWORD IDProcess)

Возвращаемое значение: дескриптор процесса или NULL в случае ошибки.

Параметры

fdwAccess определяет параметры доступа процесса к дескриптору. Приведем не­которые из его возможных значений.

• Флаг synchronize разрешает другим процессам ждать завершения этого про­цесса, используя функции ожидания, которые описаны в этой главе ниже.

• PROCESS_ALL_ACCESS — установлены все флаги доступа.

• Флаг PROCESS_TERMINATEделает возможным завершение процесса вызовом функции TerminateProcess.

• Флаг process_query_information разрешает использовать дескриптор функ­циями GetExitCodeProcess и GetPriorityClass для получения информа­ции о процессе. .,

fInherit определяет, может ли новый дескриптор быть унаследован. IDProcess содержит идентификатор процесса, которому необходим дескриптор. И наконец, выполняющийся процесс может определить имя своего загрузочного файла с помощью функции GetModuleFileName, используя в качестве параметра hModule указатель NULL. Вызов этой функции из динамической библиотеки возвратит \ имя файла DLL, а не файла . ЕХЕ, используемого библиотекой.

Копирование дескрипторов

Родительскому и дочернему процессам может потребоваться различный доступ к объекту, который определяется дескриптором, унаследованным дочерним процессом. Также процессу может потребоваться его настоящий наследуемый дескриптор вместо псевдодескриптора, создаваемого функцией GetCurrentProcess для использования дочерним процессом. Чтобы решить эту проблему, родительский процесс может соз­дать копию дескриптора с необходимыми правами доступа и видом наследования. Ниже представлена функция для копирования дескрипторов.

BOOL DuplicateHandle( HANDLE hSourceProcess, HANDLE hSource,

HANDLE hTargetProcess, LPHANDLE lphTarget,

DWORD fdwAccess, BOOL fInherit, DWORD fdwOptions);

После выполнения функции указатель lphTarget ссылается на копию исходного дескриптора hSource. Параметр hSource содержит дескриптор процесса, определяе­мого параметром hSourceProcess, и должен иметь права доступа process_dup_handle. Новый дескриптор, на который указывает переменная lphTarget, является действительным в целевом процессе hTargetProcess. Включая процесс, вызвавший функцию, здесь использованы три процесса. Вызывающий функцию процесс часто является также целевым и исходным, а дескриптор получают от функции GetCurrentProcess. Отметим, что возможно создание дескриптора в другом процессе; если вы это сделаете, то понадобится механизм для того, чтобы про­информировать его о новом экземпляре дескриптора.

Функция DuplicateHandle может быть использована для любого типа дескриптора.

Если параметр fdwAccess не подавлен флагом duplicate_same_access в пере­менной fdwOptions, то он может принимать множество значений (см. встроенную справку MSDN).

Значение параметра fdwOptions может быть любой комбинацией следующих флагов:

• DUPLICATE_CLOSE_SOURCE — исходный дескриптор будет закрыт;

• DUPLICATE_SAME_ACCSESS— параметр fdwAccess будет проигнорирован. Далее необходимо научиться определять, был ли процесс завершен.

Выход из процесса и его завершение

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

Эта функция ничего не возвращает, вызвавший ее процесс и все его потоки за­вершаются.

Для определения кода завершения другой процесс может использовать функцию GetExitCodeProcess.

BOOL GetExitCodeProcess ( HANDLE hProcess,

LPDWORD lpdwExitCode);

Процесс, определенный переменной hProcess, должен иметь права доступа PROCESS_QUERY_INFORMATION (см. функцию OpenProcess). Параметр lpdwExitCode указывает на переменную типа dword, в которую будет помещено значение. Одно из возможных значений — STILL_ACTIVE; оно указывает, что процесс не был завершен.

Один процесс может завершить другой, если его дескриптор имеет флаг доступа PROCESS_TERMINATE. Функция, завершающая процесс, также определяет код выхода из процесса.

BOOL TerminateProcess ( HANDLE hProcess, UINT uExitCode)

Ожидание завершения процесса

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

• Эти функции могут быть использованы для большого числа различных типов объектов; дескрипторы процессов — это лишь первое их применение.

• Функции могут ожидать завершения одного процесса, первого из нескольких указанных или всех процессов в группе.

• Для них может быть использована рекомендательная блокировка по времени.

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

Параметр lphObjects указывает на дескриптор одного процесса (типа hObject) или на массив различных объектов. Значение параметра cObjects (размер массива) не должно превышать константу maximum_wait_objects (в настоящее время ее зна­чение 64 определено в заголовочном файле winnt.h).

Лекция 3. Тема: Потоки и планирование

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

Каждый поток начинает выполнение с некоей входной функции. В первичном потоке таковой является WinMain. Если необходимо создать вторичный поток, в нем тоже должна быть входная функция.

Функция потока может выполнять любые задачи. Рано или поздно она закончит свою работу и вернет управление. В этот момент поток остановится, память, отведенная под его стек, будет освобождена, а счетчик пользователей его объекта ядра «поток» уменьшится на 1. Когда счетчик обнулится. этот объект ядра будет разрушен.

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]