Поделиться через


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

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

  • Функция CreatePipeполучает SECURITY_ATTRIBUTES структуру. Если сервер канала задает элемент bInheritHandle этой структуры TRUE, то дескриптора, созданные CreatePipe, можно наследовать.
  • Сервер канала может использовать функцию DuplicateHandle для изменения наследования дескриптора канала. Сервер канала может создать неустранимую копию дескриптора наследуемого канала или наследуемую копию неустранимого дескриптора канала.
  • Функция CreateProcessпозволяет серверу канала указать, наследует ли дочерний процесс все или ни один из его наследуемых дескрипторов.

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

  1. Вызовите функцию GetStdHandle, чтобы получить текущий стандартный дескриптор выходных данных; сохраните этот дескриптор, чтобы восстановить исходный стандартный выходной дескриптор после создания дочернего процесса.
  2. Вызовите функцию SetStdHandle, чтобы задать стандартный дескриптор вывода дескриптор записи в канал. Теперь родительский процесс может создать дочерний процесс.
  3. Вызовите функцию CloseHandle, чтобы закрыть дескриптор записи в канал. После того как дочерний процесс наследует дескриптор записи, родительский процесс больше не нуждается в его копировании.
  4. Вызовите SetStdHandle для восстановления исходного стандартного дескриптора выходных данных.

Дочерний процесс использует функцию GetStdHandle для получения стандартного дескриптора выходных данных, который теперь является дескриптором конца записи канала. Затем дочерний процесс использует функцию WriteFile для отправки выходных данных в канал. Когда дочерний объект завершит работу с каналом, он должен закрыть дескриптор канала, вызвав CloseHandle или завершив его завершение, которое автоматически закрывает дескриптор.

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

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

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