Process SecurityNormally, CreateProcess gives PROCESS_ALL_ACCESS rights. There are, however, several specific rights, including PROCESS_QUERY_INFORMATION, CREATE_PROCESS, PROCESS_TERMINATE, PROCESS_SET_INFORMATION, DUPLICATE_HANDLE, and CREATE_THREAD. In particular, it can be useful to limit PROCESS_TERMINATE rights to the parent process given the frequently mentioned dangers of terminating a running process. Chapter 15 describes security attributes for processes and other objects. UNIX waits for process termination using wait and waitpid, but there are no time-outs even though waitpid can poll (there is a nonblocking option). These functions wait only for child processes, and there is no equivalent to the multiple wait on a collection of processes, although it is possible to wait for all processes in a process group. One slight difference is that the exit code is returned with wait and waitpid, so there is no need for a separate function equivalent to GetExit- CodeProcess.UNIX also supports environment strings similar to those in Windows. getenv (in the C library) has the same functionality as GetEnvironmentVariable except that the programmer must be sure to have a sufficiently large buffer. putenv, setenv, and unsetenv (not in the C library) are different ways to add, change, and remove variables and their values, with functionality equivalent to SetEnvironmentVariable.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 simple 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; however, the project and executable (grep.exe) are in the Examples file.The command line to the program is of the form grepMP pattern F1 F2 ... FNThe program, Program 6-1, performs the following processing:
Figure 6-3 shows the processing performed by Program 6-1, and Run 6-1 shows program execution and timing results.
Figure 6.3 - File Searching using Multiple ProcessesProgram 6-1 grepMP: Parallel Searching/* Chapter 6. grepMP. *//* Multiple process version of grep command. */#include "Everything.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, exitCode, dwCreationFlags = 0;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. */grep pattern argv [3]argv [1], argv [2], ..., argv [N+1]for (i = 1; i <= N; i++) {StartUp.hStdOut =CreateFile (Temp [i])CreateProcess (grep patternargv [i+1])}WaitForMultipleObjects;···/* Display search results */for (i = 1; i <= N; i++) {CreateProcess (cat Temp [i])WaitForSingleObject;} ExitProcess()grep pattern argv ExitProcess()grep pattern argv [2] ExitProcess()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 ("grep \"%s\" \"%s\""),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,dwCreationFlags, 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], &exitCode) && exitCode==0){/* Pattern was detected -- List results. */if (argc > 3) _tprintf (_T ("%s:\n"), argv[iProc + 2]);_stprintf (commandLine, _T ("cat \"%s\""),procFile[iProc].tempFile);CreateProcess (NULL, commandLine, NULL, NULL, TRUE,dwCreationFlags, 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;}Run 6-1 shows grepMP execution for large and small files, and the run contrasts sequential grep execution with parallel grepMP execution to perform the same task. The test computer has four processors; a single or dual processor computer will give different timing results. Notes after the run explain the test operation and results.
Run 6-1 grepMP: Parallel Searching Run 6-1 uses files and obtains results as follows:
Processes in a Multiprocessor EnvironmentIn Program 6-1, the processes and their primary (and only) threads run almost totally independently of one another. The only dependence is created at the end of the parent process as it waits for all the processes to complete so that the output files can be processed sequentially. Therefore, the Windows scheduler can and will run the process threads concurrently on the separate processors of a multiprocessor computer. As Run 6-1 shows, this can result in substantial performance improvement when performance is measured as elapsed time to execute the program, and no explicit program actions are required to get the performance improvement. The performance improvement is not linear in terms of the number of processors due to overhead costs and the need to output the results sequentially. Nonetheless, the improvements are worthwhile and result automatically as a consequence of the program design, which delegates independent computational tasks to independent processes. It is possible, however, to constrain the processes to specific processors if you wish to be sure that other processors are free to be allocated to other critical tasks. This can be accomplished using the processor affinity mask (see Chapter 9) for a process or thread. Finally, it is possible to create independent threads within a process, and these threads will also be scheduled on separate processors. Chapter 7 describes threads and related performance issues.