Наследование дескрипторов канала
Сервер канала определяет, могут ли его дескрипторы наследоваться следующими способами:
- Функция CreatePipe получает структуру SECURITY_ATTRIBUTES . Если сервер канала задает элементу bInheritHandle этой структуры значение TRUE, дескрипторы, созданные с помощью CreatePipe , могут быть унаследованы.
- Сервер канала может использовать функцию DuplicateHandle для изменения наследования дескриптора канала. Сервер канала может создать ненаследуемую копию наследуемого дескриптора канала или наследуемую копию ненаследуемого дескриптора канала.
- Функция CreateProcess позволяет серверу конвейера указать, наследует ли дочерний процесс все наследуемые дескрипторы или нет.
Когда дочерний процесс наследует дескриптор канала, система разрешает процессу доступ к каналу. Однако родительский процесс должен передавать значение дескриптора дочернему процессу. Родительский процесс обычно выполняет это путем перенаправления стандартного дескриптора вывода в дочерний процесс, как показано на следующих шагах:
- Вызовите функцию GetStdHandle , чтобы получить текущий стандартный дескриптор вывода; Сохраните этот дескриптор, чтобы восстановить исходный стандартный выходной дескриптор после создания дочернего процесса.
- Вызовите функцию SetStdHandle , чтобы задать стандартный дескриптор вывода дескриптор записи в канал. Теперь родительский процесс может создать дочерний процесс.
- Вызовите функцию CloseHandle , чтобы закрыть дескриптор записи в канале. После того как дочерний процесс наследует дескриптор записи, его копирование родительскому процессу больше не требуется.
- Вызовите Метод SetStdHandle , чтобы восстановить исходный стандартный выходной дескриптор.
Дочерний процесс использует функцию GetStdHandle для получения стандартного дескриптора вывода, который теперь является дескриптором для записи конца канала. Затем дочерний процесс использует функцию WriteFile для отправки выходных данных в канал. Когда дочерний элемент завершит работу с каналом, он должен закрыть дескриптор канала, вызвав CloseHandle или завершив, что автоматически закрывает дескриптор.
Родительский процесс использует функцию ReadFile для получения входных данных из канала. Данные записываются в анонимный канал в виде потока байтов. Это означает, что родительский процесс, считывающий данные из канала, не может различать байты, записанные в отдельных операциях записи, если родительский и дочерний процессы не используют протокол, указывающий, где заканчивается операция записи. При закрытии всех дескрипторов записи в канал функция ReadFile возвращает ноль. Важно, чтобы родительский процесс закрыл свой дескриптор до конца записи канала перед вызовом ReadFile. Если этого не сделать, операция ReadFile не может вернуть ноль, так как родительский процесс имеет открытый дескриптор для записи конца канала.
Процедура перенаправления стандартного дескриптора ввода аналогична процедуре перенаправления стандартного дескриптора вывода, за исключением того, что дескриптор чтения канала используется в качестве стандартного дескриптора ввода дочернего элемента. В этом случае родительский процесс должен гарантировать, что дочерний процесс не наследует дескриптор записи канала. Если этого не сделать, операция ReadFile , выполняемая дочерним процессом, не может вернуть ноль, так как дочерний процесс имеет открытый дескриптор для записи конца канала.
Пример программы, которая использует анонимные каналы для перенаправления стандартных дескрипторов дочернего процесса, см. в разделе Создание дочернего процесса с перенаправленными входными и выходными данными.