- Windows Processes and Threads
- Process Creation
- 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
- Example: Using Job Objects
- Summary
- Exercises
Example: Using Job Objects
Program 6-7, JobObjectShell, illustrates using job objects to limit process execution time and to obtain user time statistics. JobObjectShell is a simple extension of JobShell that adds a command line time limit argument, in seconds. This limit applies to every process that JobObjectShell manages.
Program 6-7. JobObjectShell: Monitoring Processes with a Job Object
/* Chapter 6 */ /* JobObjectShell.c JobShell extension Enhances JobShell with a time limit on each process. The process time limit (seconds) is argv[1] (if present) 0 or omitted means no process time limit */ #include "Everything.h" #include "JobManagement.h" #define MILLION 1000000 HANDLE hJobObject = NULL; JOBOBJECT_BASIC_LIMIT_INFORMATION basicLimits = {0, 0, JOB_OBJECT_LIMIT_PROCESS_TIME}; int _tmain (int argc, LPTSTR argv[]) { LARGE_INTEGER processTimeLimit; . . . hJobObject = NULL; processTimeLimit.QuadPart = 0; if (argc >= 2) processTimeLimit.QuadPart = atoi(argv[1]); basicLimits.PerProcessUserTimeLimit.QuadPart = processTimeLimit.QuadPart * 10 * MILLION; hJobObject = CreateJobObject(NULL, NULL); SetInformationJobObject(hJobObject, JobObjectBasicLimitInformation, &basicLimits, sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION)); . . . /* Process commands. Call Jobbg, Jobs, etc. - listed below */ CloseHandle (hJobObject); return 0; } /* Jobbg: Execute a command line in the background, put the job identity in the user's job file, and exit. */ int Jobbg (int argc, LPTSTR argv[], LPTSTR command) { /* Execute the command line (targv) and store the job id, the process id, and the handle in the jobs file. */ DWORD fCreate; LONG jobNumber; BOOL flags[2]; STARTUPINFO startUp; PROCESS_INFORMATION processInfo; LPTSTR targv = SkipArg (command); GetStartupInfo (&startUp); /* Determine the options. */ Options (argc, argv, _T ("cd"), &flags[0], &flags[1], NULL); /* Skip over the option field as well, if it exists. */ if (argv[1][0] == '-') targv = SkipArg (targv); fCreate = flags[0] ? CREATE_NEW_CONSOLE : flags[1] ? DETACHED_PROCESS : 0; /* Create the job/thread suspended. Resume it once the job is entered properly. */ CreateProcess (NULL, targv, NULL, NULL, TRUE, fCreate | CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &startUp, &processInfo); AssignProcessToJobObject(hJobObject, processInfo.hProcess); jobNumber = GetJobNumber (&processInfo, targv); if (jobNumber >= 0) ResumeThread (processInfo.hThread); else { TerminateProcess (processInfo.hProcess, 3); CloseHandle (processInfo.hThread); CloseHandle (processInfo.hProcess); return 5; } CloseHandle (processInfo.hThread); CloseHandle (processInfo.hProcess); _tprintf (_T (" [%d] %d\n"), jobNumber, processInfo.dwProcessId); return 0; } /* Jobs: List all running or stopped jobs that have been created by this user under job management; that is, have been started with the jobbg command. List summary process count and user time information. */ int Jobs (int argc, LPTSTR argv[], LPTSTR command) { JOBOBJECT_BASIC_ACCOUNTING_INFORMATION BasicInfo; DisplayJobs (); /* Not job objects, but jobbg created processes */ /* Dispaly the job object information */ QueryInformationJobObject(hJobObject, JobObjectBasicAccountingInformation, &BasicInfo, sizeof(JOBOBJECT_BASIC_ACCOUNTING_INFORMATION), NULL); _tprintf (_T("Total Processes: %d, Active: %d, Terminated: %d.\n"), BasicInfo.TotalProcesses, BasicInfo.ActiveProcesses, BasicInfo.TotalTerminatedProcesses); _tprintf (_T("User time all processes: %d.%03d\n"), BasicInfo.TotalUserTime.QuadPart / MILLION, (BasicInfo.TotalUserTime.QuadPart % MILLION) / 10000); return 0; }
When you list the running processes, you will also see the total number of processes and the total user time on a four-processor computer.
First, we'll modify the usual order and show Run 6-7, which runs the command:
JobObjectShell 60
Run 6-7 JobObjectShell Monitoring Processes with a Job Object
to limit each process to a minute. The example then runs to shell commands:
timep grep 1234561 l2.txt l3.txt l4.txt timep grepMP 1234561 l2.txt l3.txt l4.txt
as in Run 6-6. Note how the jobs command counts the processes that timep creates as well as those that grepMP creates to search the files, resulting in seven processes total. There is also a lot of contention for the console, mixing output from several processes, so you might want to run this example with the -c option.
There are also a few unexpected results, which are described for further investigation in Exercise 6–12.
Program 6-7 gives the JobObjectShell listing; it's an extension of JobShell (Program 6-3), so the listing is shortened to show the new code. There are some deviations from the MSDN documentation, which are described in Exercise 6–12 for investigation.