`
Читать книги » Книги » Компьютеры и Интернет » Программирование » Джонсон Харт - Системное программирование в среде Windows

Джонсон Харт - Системное программирование в среде Windows

1 ... 49 50 51 52 53 ... 142 ВПЕРЕД
Перейти на страницу:

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

Настало время посмотреть на процессы 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;

Процессы в многопроцессорной среде

В программе 6.1 процессы и их основные (и только эти) потоки выполняются практически полностью независимо друг от друга. Единственная зависимость между ними проявляется лишь в конце выполнения родительского процесса, поскольку он ожидает завершения выполнения каждого из них, чтобы перейти к последовательной обработке выходных файлов. Поэтому в SMP-системах планировщик Windows может и будет обеспечивать параллельное выполнение потоков процесса на нескольких независимых процессорах. В результате этого производительность, если оценивать ее по времени выполнения всей программы, значительно повышается, причем для этого с вашей стороны не требуется предпринимать никаких действий.

Типичные результаты тестирования производительности приведены в приложении В. Ввиду выполнения программой ряда вспомогательных операций, а также необходимости последовательного вывода результатов, зависимость производительности от количества процессоров не является линейной. Тем не менее, улучшение производительности налицо, и это автоматически обеспечивается организацией программы, которая предусматривает передачу выполнения независимых вычислительных задач независимым процессам.

Вместе с тем, существует возможность привязки процессов к определенным процессорам, что позволяет всегда быть уверенным в том, что другие процессоры остаются свободными и их можно использовать для решения каких-либо иных, критических задач. Это достигается за счет применения маски родства процессора (processor affinity mask) (см. главу 9) в объекте задачи. Объекты задач (job objects) описываются в одном из следующих разделов настоящей главы. 

Наконец, внутри процесса можно создавать независимые потоки, и для этих потоков также будет спланировано выполнение с использованием отдельных процессоров SMP для каждого из них. Связь между использованием потоков и показателями производительности обсуждается в главе 7.

Временные характеристики процесса

Воспользовавшись функцией GetProcessTimes, которая в Windows 9x отсутствует, можно получить различные временные характеристики процесса, а именно: истекшее время (elapsed time), время, затраченное ядром (kernel time), и пользовательское время (user time). 

BOOL GetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime) 

Дескриптор процесса может ссылаться как на процесс, который продолжает выполняться, так и на процесс, выполнение которого прекратилось. Вычитая время создания процесса (creation time) из времени завершения процесса (exit time), мы получаем истекшее время, как показано в следующем примере. Тип данных FILETIME является 64-битовым; для вычисления указанной разности объедините переменную этого типа с переменной тип LARGE_INTEGER в структуру типа union. Ранее преобразование и отображение отметок времени файлов было продемонстрировано в главе 3 на примере программы lsw.

Функция GetThreadTimes аналогична только что описанной, но требует указания дескриптора потока в качестве параметра. Управлению потоками посвящена глава 7.

Пример: временные характеристики процессов

Наш следующий пример (программа 6.2) представляет собой команду timep (от time print — вывод временных параметров), аналогичную UNIX-команде time (поскольку команда time поддерживается процессором командной строки, мы должны использовать для нашей команды другое имя). Программа позволяет вывести все три временные характеристики, однако в Windows 9x будет доступно лишь истекшее время процесса.

Одним из возможных применений этой команды является сравнительный анализ времени выполнения и эффективности различных версий функций копирования и преобразования файлов из ASCII в Unicode, реализованных в предыдущих главах.

1 ... 49 50 51 52 53 ... 142 ВПЕРЕД
Перейти на страницу:

Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Джонсон Харт - Системное программирование в среде Windows, относящееся к жанру Программирование. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.

Комментарии (0)