Home > Articles > Operating Systems, Server > Microsoft Servers

  • Print
  • + Share This
This chapter is from the book

Example: Parallel Pattern Searching

Now is the time to put Windows processes to the test. This example, grepMP, creates processes to search for patterns in files, one process per search file. The pattern search program is modeled after the UNIX grep utility, although the technique would apply to any program that uses standard output. The search program should be regarded as a black box and is simply an executable program to be controlled by a parent process.

The command line to the program is of the form

grepMP pattern F1 F2 ... FN
   

The program, Program 6-1, performs the following processing:

  • Each input file, F1 to FN, is searched using a separate process running the same executable. The program creates a command line of the form grep pattern FK.

  • The handle of the temporary file, specified to be inheritable, is assigned to the hStdOutput field of the new process's start-up information structure.

  • Using WaitForMultipleObjects, the program waits for all search processes to complete.

  • As soon as all searches are complete, the results (temporary files) are displayed in order, one at a time. A process to execute the cat utility (Program 2-3) outputs the temporary file.

  • WaitForMultipleObjects is limited to MAXIMUM_WAIT_OBJECTS (64) handles, so it is called multiple times.

  • The program uses the grep process exit code to determine whether a specific process detected the pattern.

Figure 6-3 shows the processing performed by Program 6-1.

Example 6-1. grepMP: Parallel Searching

/*   Chapter 6. grepMP. */
/*   Multiple process version of grep command. */

#include "EvryThng.h"
int _tmain (DWORD argc, LPTSTR argv [])
/* Create a separate process to search each file on the
   command line. Each process is given a temporary file,
   in the current directory, to receive the results. */
{
   HANDLE hTempFile;
   SECURITY_ATTRIBUTES StdOutSA = /* SA for inheritable handle. */
          {sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
   TCHAR CommandLine [MAX_PATH + 100];
   STARTUPINFO StartUpSearch, StartUp;
   PROCESS_INFORMATION ProcessInfo;
   DWORD iProc, ExCode;
   HANDLE *hProc; /* Pointer to an array of proc handles. */
   typedef struct {TCHAR TempFile [MAX_PATH];} PROCFILE;
   PROCFILE *ProcFile; /* Pointer to array of temp file names. */
   GetStartupInfo (&StartUpSearch);
   GetStartupInfo (&StartUp);
   ProcFile = malloc ((argc - 2) * sizeof (PROCFILE));
   hProc = malloc ((argc - 2) * sizeof (HANDLE));

   /* Create a separate "grep" process for each file. */
   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); /* For search results. */
      hTempFile = /* This handle is inheritable */
         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);

      /* Create a process to execute the command line. */
      CreateProcess (NULL, CommandLine, NULL, NULL,
            TRUE, 0, NULL, NULL, &StartUpSearch, &ProcessInfo);
      /* Close unwanted handles. */
      CloseHandle (hTempFile); CloseHandle (ProcessInfo.hThread);
      hProc [iProc] = ProcessInfo.hProcess;
   }

   /* Processes are all running. Wait for them to complete. */
   for (iProc = 0; iProc < argc - 2; iProc += MAXIMUM_WAIT_OBJECTS)
      WaitForMultipleObjects ( /* Allows a large # of processes */
            min (MAXIMUM_WAIT_OBJECTS, argc - 2 - iProc),
            &hProc [iProc], TRUE, INFINITE);
   /* Result files sent to std output using "cat." */
   for (iProc = 0; iProc < argc - 2; iProc++) {
      if (GetExitCodeProcess(hProc [iProc], &ExCode) && ExCode==0) {
         /* Pattern was detected -- List results. */
         if (argc > 3) _tprintf (_T ("%s:\n"), argv [iProc + 2]);
         fflush (stdout); /* Multiple processes use stdout. */
         _stprintf (CommandLine, _T ("%s%s"),
               _T ("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;
}

06fig03.gifFigure 6-3 File Searching Using Multiple Processes

  • + Share This
  • 🔖 Save To Your Account