• По завершении всех процессов поиска осуществляется поочередный вывод результатов (временных файлов). Вывод временного файла осуществляет процесс, выполняющий утилиту cat (программа 2.3).
• Возможности функции WaitForMultipleObjects ограничиваются лишь максимально допустимым количеством дескрипторов, которое устанавливается значением MAXIMUM_WAIT_OBJECTS (64), поэтому она вызывается многократно.
• Для определения успешности попытки нахождения данным процессом заданного шаблона программа использует код завершения процесса grep.
Порядок обработки файлов программой 6.1 иллюстрируется на рис. 6.3.
Рис. 6.З. Поиск текстового шаблона в файлах с использованием нескольких процессов
/* Глава 6. grepMP. */
/* Версия команды grep, использующая несколько процессов. */
#include "EvryThng.h"
int _tmain(DWORD argc, LPTSTR argv[])
/* Для выполнения поиска в каждом из файлов, указанных в командной строке, создается отдельный процесс. Каждому процессу предоставляется временный файл в текущем каталоге, в котором сохраняются результаты. */
{
HANDLE hTempFile;
SECURITY_ATTRIBUTES StdOutSA = /* Атрибуты защиты для наследуемого дескриптора. */
{sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
TCHAR CommandLine[MAX_PATH + 100];
STARTUPINFO StartUpSearch, Startup;
PROCESS_INFORMATION ProcessInfo;
DWORD iProc, ExCode;
HANDLE *hProc; /* Указатель на массив дескрипторов процессов. */
typedef struct {TCHAR TempFile[MAX_PATH];} PROCFILE;
PROCFILE *ProcFile; /* Указатель на массив имен временных файлов. */
GetStartupInfo(&StartUpSearch);
GetStartupInfo(&StartUp);
ProcFile = malloc((argc – 2) * sizeof(PROCFILE));
hProc = malloc((argc – 2) * sizeof(HANDLE));
/* Создать для каждого файла отдельный процесс "grep". */
for (iProc = 0; iProc < argc – 2; iProc++) {
_stprintf(CommandLine, _T("%s%s %s"), _T("grep "), argv[1], argv[iProc + 2]);
GetTempFileName(_T("."), _T("gtm"), 0, ProcFile[iProc].TempFile); /* Для хранения результатов поиска.*/
hTempFile = /* Этот дескриптор является наследуемым */
CreateFile(ProcFile[iProc].TempFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &StdOutSA, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
StartUpSearch.dwFlags = STARTF_USESTDHANDLES;
StartUpSearch.hStdOutput = hTempFile;
StartUpSearch.hStdError = hTempFile;
StartUpSearch.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
/* Создать процесс для выполнения командной строки. */
CreateProcess(NULL, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartUpSearch, &ProcessInfo);
/* Закрыть ненужные дескрипторы. */
CloseHandle(hTempFile);
CloseHandle(ProcessInfo.hThread);
hProc[iProc] = ProcessInfo.hProcess;
}
/* Выполнить все процессы и дождаться завершения каждого из них. */
for (iProc = 0; iProc < argc – 2; iProc += MAXIMUM_WAIT_OBJECTS) WaitForMultipleObjects( /* Разрешить использование достаточно большого количества процессов */