Замечание

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

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

Созданному объекту ядра «процесс» присваивается уникальный идентификатор; ни у каких других объектов этого типа в системе не может быть одинаковых идентификаторов. Это же касается и объектов ядра «поток». Причем идентификаторы процесса и потока тоже разные, и их значения никогда не бывают нулевыми. Завершая свою работу, CreateProcess заносит значения идентификаторов в элементы dwProcessId и dwThreadId структуры PROCESS_INFORMATION Эти идентификаторы просто облегчают определение процессов и потоков в системе; их используют, как правило, лишь cпециализированные утилиты вроде Task Manager.

Подчеркну еще один чрезвычайно важный момент система способна повторно использовать идентификаторы процессов и потоков. Например, при создании процесса система формирует объект «процесс», присваивая ему идентификатор со значением, допустим, 122. Создавая новый объект «процесс», система уже не присвоит ему данный идентификатор. Но после выгрузки из памяти первого объекта следующему cоздаваемому объекту «процесс» может быть присвоен тот же идентификатор — 122.

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

Иногда программе приходится определять свой родительский процесс. Однако родственные связи между процессами существуют лишь на стадии создания дочернего процесса. Непосредственно перед началом исполнения кода в дочернем процессе Windows перестает учитывать его родственные связи. В предыдущих версиях Windows не было функций, которые позволяли бы программе обращаться с запросом к ее родительскому процессу. Но ToolHelp-функции, появившиеся в современных версиях Windows, сделали это возможным. С этой целью можно использовать структуру PROCESSENTRY32: ее элемент th32ParentProcessID возвращает идентификатор «родителя» данного процесса. Тем не менее, если программе нужно взаимодействовать с родительским процессом, от идентификаторов лучше отказаться. Для определения родительского процесса существуют более надежные механизмы: объекты ядра, описатели окон и т. д.

Единственный способ добиться того, чтобы идентификатор процесса или потока не использовался повторно, — не допускать разрушения объекта ядра "процесс" или "поток". Если только что создан новый процесс или поток, то можно просто не закрывать описатели на эти объекты — вот и все. А по окончании операций с идентификатором, вызвать функцию CloseHandle и освободите соответствующие объекты ядра. Однако для дочернего процесса этот способ не годится, если только он не унаследовал описатели объектов ядра от родительского процесса.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: