Что это значит:«Дочерний процесс может наследовать дескриптор»?
Вопрос
Существуют некоторые объекты Win32, которые, согласно SDK, могут быть «наследованы» дочерним процессам, созданным данным процессом.(События, мьютексы, каналы,...)
Что это на самом деле означает?
Допустим, у меня есть именованный объект события, созданный с помощью CreateEvent
, один раз с bInheritHandle == true
, и в другой раз == false
.
Теперь я запускаю дочерний процесс.Как эти два дескриптора событий влияют на дочерний процесс?В каких сценариях они различаются?
Решение
Если вы создаете/открываете объект и разрешаете наследование этого дескриптора, дочерние процессы, которым разрешено наследовать дескрипторы (например,вы можете указать bInheritHandles = TRUE
для CreateProcess) будут иметь копии этих дескрипторов.Эти унаследованные дескрипторы будут иметь те же значения дескрипторов, что и родительские дескрипторы.Так, например:
CreateEvent
возвращает дескриптор объекта события, дескриптор0x1234
.- Вы разрешаете наследование этого дескриптора.
- Вы создаете дочерний процесс, который наследует ваши дескрипторы.
- Этот дочерний процесс теперь может использовать дескриптор
0x1234
без необходимости звонитьCreateEvent
илиOpenEvent
.Например, вы можете передать значение дескриптора в командной строке дочернего процесса.
Это полезно для безымянных объектов — поскольку они безымянны, другие процессы не могут их открыть.Используя наследование дескрипторов, дочерние процессы могут получить дескрипторы безымянных объектов, если вы этого захотите.
Другие советы
Один момент, который не был упомянут в существующих ответах, заключается в том, что разрешение дочернему процессу наследовать дескрипторы влияет не только на дочерний процесс;это также может повлиять на время жизни объекта, на который ссылаются дескрипторы.Если родительский процесс завершается, дескрипторы дочернего процесса сохранят объект живым.
Разрешая дочернему процессу наследовать дескрипторы, вы должны учитывать, приведет ли это к тому, что объект будет жить дольше, чем следовало бы;например, некоторые приложения хотят разрешить запуск только одного экземпляра одновременно и могут сделать это, создав объект события с заданным именем и проверив, существует ли он уже.Если они создадут дочерний процесс, который наследует этот объект события и переживет родительский, это может привести к ложному срабатыванию.
Чаще всего унаследованный дескриптор файла может привести к тому, что файл будет использоваться (и, следовательно, будет недоступен) дольше, чем следовало бы.
По этой причине передовой практикой является:
Сделайте все дескрипторы ненаследуемыми, если только их наследование не требуется.
Если подпроцессу не нужно наследовать дескрипторы, передайте
FALSE
дляbInheritHandles
.Если подпроцессу необходимо наследовать дескрипторы, разрешить ему наследовать только те конкретные дескрипторы, которые необходимы.
С другой стороны, иногда это может быть полезно;например, если вы хотеть дочерний процесс считается экземпляром родительского процесса или файл остается недоступным до тех пор, пока дочерний процесс не завершится.Другой трюк заключается в том, чтобы дочерний элемент унаследовал дескриптор именованного объекта, а затем использовал существование или отсутствие объекта, чтобы определить, жив ли еще дочерний процесс, без необходимости передавать дескриптор процесса или идентификатор процесса.
Если вы создаете событие и разрешаете наследование дескриптора дочерним процессам, тогда дочерний процесс может использовать дескриптор того же объекта, созданного родительским.Это можно использовать таким образом, чтобы дочерний элемент использовал дескриптор события, чтобы сигнализировать родительскому элементу о завершении задачи (есть много других применений для наследуемых дескрипторов объектов событий).
РЕДАКТИРОВАТЬ:Удалена дезинформация.