Рис. 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 != '\0') {
Command1[i] = *targv;
targv++;
i++;
}
Command1[i] = '\0';
/* Пропуск до начала второй команды. */
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;
}
Именованные каналы (named pipes) предлагают ряд возможностей, которые делают их полезными в качестве универсального механизма реализации приложений на основе IPC, включая приложения, требующие сетевого доступа к файлам, и клиент-серверные системы [31] Это утверждение нуждается в дополнительных разъяснениях. Для большинства сетевых приложений и высокоуровневых протоколов (http, ftp и так далее) более предпочтительным является интерфейс Windows Sockets API, особенно в тех случаях, когда требуется обеспечить межплатформенное взаимодействие с системами, отличными от Windows, на основе протокола TCP/IP. Многие разработчики предпочитают ограничивать использование именованных каналов лишь случаями IPC в пределах обособленной системы или в сетях Windows.
, хотя для реализации простых вариантов IPC, ориентированных на байтовые потоки, как в предыдущем примере, в котором взаимодействие процессов ограничивается рамками одной системы, анонимных каналов вам будет вполне достаточно. К числу упомянутых возможностей (часть которых обеспечивается дополнительно) относятся следующие:
• Именованные каналы ориентированы на обмен сообщениями, поэтому процесс, выполняющий чтение, может считывать сообщения переменной длины именно в том виде, в каком они были посланы процессом, выполняющим запись.
Читать дальше