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

Пример: параллельный поиск указанного текстового шаблона

Пример: параллельный поиск указанного текстового шаблона

Настало время посмотреть на процессы Windows в действии. Приведенная ниже в качестве примера программа grepMP создает процессы для поиска указанного текстового шаблона в файлах, по одному процессу на каждый файл. Эта программа моделирует UNIX-утилиту grep, хотя используемая нами методика применима к любой программе, которая полагается на стандартный вывод. Рассматривайте программу поиска как "черный ящик" и считайте, что она является просто исполняемой программой, выполнение которой должно контролироваться родительским процессом.

Командная строка программы имеет следующий вид:

grepMP шаблон F1 F2 … FN

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

• Для поиска указанного шаблона в каждом из входных файлов, от F1 до FN, используется отдельный процесс, запускающий один и тот же исполняе мый модуль. Для каждого процесса программа создает командную строку такого вида: grep шаблон FK.

• Полю hStdOut структуры STARTUPINFO нового процесса присваивается значение дескриптора временного файла, который определяется как наследуемый.

• Программа организует ожидание завершения всех процессов поиска, используя для этого функцию WaitForMultipleObjects.

• По завершении всех процессов поиска осуществляется поочередный вывод результатов (временных файлов). Вывод временного файла осуществляет процесс, выполняющий утилиту cat (программа 2.3).

• Возможности функции WaitForMultipleObjects ограничиваются лишь максимально допустимым количеством дескрипторов, которое устанавливается значением MAXIMUM_WAIT_OBJECTS (64), поэтому она вызывается многократно.

• Для определения успешности попытки нахождения данным процессом заданного шаблона программа использует код завершения процесса grep.

Порядок обработки файлов программой 6.1 иллюстрируется на рис. 6.3. 


Рис. 6.З. Поиск текстового шаблона в файлах с использованием нескольких процессов

Программа 6.1. grepMP: выполнение параллельного поиска текстового шаблона 

/* Глава 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( /* Разрешить использование достаточно большого количества процессов */
  min(MAXIMUM_WAIT_OBJECTS, argc – 2 – iProc), &hProc [iProc], TRUE, INFINITE);
 /* Переслать результирующие файлы на стандартный вывод с использованием утилиты cat */ 
 for (iProc = 0; iProc < argc – 2; iProc++) {
  if (GetExitCodeProcess(hProc[iProc], &ExCode) && ExCode==0) {
   /* Обнаружен шаблон — Вывести результаты. */
   if (argc > 3) _tprintf(_T("%s:n"), argv [iProc + 2]);
   fflush(stdout); /* Использование стандартного вывода несколькими процессами. */
   _stprintf(CommandLine, _T("%s%s"), _Т("cat "), ProcFile[iProc].TempFile);
   CreateProcess(NULL, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartUp, &ProcessInfo);
   WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
   CloseHandle(ProcessInfo.hProcess);
   CloseHandle(ProcessInfo.hThread);
  }
  CloseHandle(hProc [iProc]);
  DeleteFile(ProcFile[iProc].TempFile);
 }
 free(ProcFile);
 free(hProc);
 return 0;
}
 

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


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