Книга: Системное программирование в среде Windows

Пример: перенаправление ввода/вывода с использованием анонимного канала

Пример: перенаправление ввода/вывода с использованием анонимного канала

В программе 11.1 представлен родительский процесс, который создает два процесса из командной строки и соединяет их каналом. Родительский процесс устанавливает канал и осуществляет перенаправление стандартного ввода/вывода. Обратите внимание на то, каким образом задается свойство наследования дескрипторов анонимного канала и как организуется перенаправление стандартного ввода/вывода на два дочерних процесса; эти методики описаны в главе 6.

Местоположение оператора WriteFile в блоке Program2 на рис. 11.1 справа предполагает, что программа считывает большой объем данных, обрабатывает их, и лишь после этого записывает результаты. Эту запись можно было бы осуществлять и внутри цикла, выводя результаты после каждого считывания.


Рис. 11.1. Межпроцессное взаимодействие с использованием анонимного канала

Дескрипторы каналов и потоков должны закрываться при первой же возможности. На рис. 11.1 закрытие дескрипторов не отражено, однако это делается в программе 11.1. Родительский процесс должен закрыть дескриптор устройства стандартного вывода сразу же после создания первого дочернего процесса, чтобы второй процесс мог распознать метку конца файла, когда завершится выполнение первого процесса. В случае существования открытого дескриптора первого процесса второй процесс не смог бы завершиться, поскольку система не обозначила бы конец файла.

В программе 11.1 используется непривычный синтаксис: две команды, разделенные символом =, обозначающим канал. Использование для этой цели символа вертикальной черты (|) привело бы к возникновению конфликта с системным командным процессором. Рисунок 11.1 является схематическим представлением выполнения следующей команды:

$ pipe Program1 аргументы = Program2 аргументы

При использовании средств командного процессора UNIX или Windows соответствующая команда имела бы следующий вид:

$ Program1 аргументы | Program2 аргументы

Программа 11.1. pipe: межпроцессное взаимодействие с использованием анонимных каналов 

#include "EvryThng.h"
int _tmain(int argc, LPTSTR argv[])
/* Соединение двух команд с помощью канала в командной строке: pipe команда1 = команда2 */
{
 DWORD i = 0;
 HANDLE hReadPipe, hWritePipe;
 TCHAR Command1[MAX_PATH];
 SECURITY_ATTRIBUTES PipeSA = /* Для наследуемых дескрипторов. */
  {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
 PROCESS_INFORMATION ProcInfo1, ProcInfo2;
 STARTUPINFO StartInfoCh1, StartInfoCh2;
 LPTSTR targv = SkipArg(GetCommandLine());
 GetStartupInfo(&StartInfoCh1);
 GetStartupInfo(&StartInfoCh2);
 /* Найти символ "=", разделяющий две команды. */
 while (*targv != '=' && *targv != '') {
  Command1[i] = *targv;
  targv++;
  i++;
 }
 Command1[i] = '';
 /* Пропуск до начала второй команды. */
 targv = SkipArg(targv);
 CreatePipe(&hReadPipe, &hWritePipe, &PipeSA, 0);
 /* Перенаправить стандартный вывод и создать первый процесс. */
 StartInfoCh1.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
 StartInfoCh1.hStdError = GetStdHandle(STD_ERROR_HANDLE);
 StartInfoCh1.hStdOutput = hWritePipe;
 StartInfoCh1.dwFlags = STARTF_USESTDHANDLES;
 CreateProcess(NULL, (LPTSTR)Command1, NULL, NULL, TRUE /* Унаследовать дескрипторы. */, 0, NULL, NULL, &StartInfoCh1, &ProcInfo1);
 CloseHandle(ProcInfo1.hThread);
 /* Закрыть дескриптор записи канала, поскольку он больше не нужен, чтобы вторая команда могла обнаружить конец файла. */
 CloseHandle(hWritePipe);
 /* Повторить операции (симметричным образом) для второго процесса. */
 StartInfoCh2.hStdInput = hReadPipe;
 StartInfoCh2.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
 StartInfoCh2.hStdError = GetStdHandle(STD_ERROR_HANDLE);
 StartInfoCh2.dwFlags = STARTF_USESTDHANDLES;
 CreateProcess(NULL, (LPTSTR)targv, NULL, NULL, TRUE, 0, NULL, NULL, &StartInfoCh2, &ProcInfo2);
 CloseHandle(ProcInfo2.hThread);
 CloseHandle(hReadPipe);
 /* Ожидать завершения первого и второго процессов. */
 WaitForSingleObject(ProcInfo1.hProcess, INFINITE);
 CloseHandle(ProcInfo1.hProcess);
 WaitForSingleObject(ProcInfo2.hProcess, INFINITE);
 CloseHandle(ProcInfo2.hProcess);
 return 0;
}

Оглавление книги


Генерация: 0.704. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз