- Windows Processes and Threads
- Process Creation
- Process Handle Counts
- Process Identities
- Duplicating Handles
- Exiting and Terminating a Process
- Waiting for a Process to Terminate
- Environment Blocks and Strings
- Example: Parallel Pattern Searching
- Processes in a Multiprocessor Environment
- Process Execution Times
- Example: Process Execution Times
- Generating Console Control Events
- Example: Simple Job Management
- Job Objects
- Summary
- Exercises
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; }
Figure 6-3 File Searching Using Multiple Processes