I l @ ve RuBoard |
MotivationProcess creation and management is a core part of most general-purpose operating systems (though Section 6.2 describes why some embedded operating systems don't provide process capabilities). Operating systems that do support multiple processes provide functionality to
Given the maturity of these OS process management capabilities, you might expect a unified standard to govern this area. For a variety of factors, unfortunately , that's not the case. For instance, the following table outlines the key differences between POSIX/UNIX and Win32 process management:
Although a complete discussion of OS multiprocessing mechanisms is beyond the scope of this book (see [Sch94, Ste92, Ric97] for more information), this comparison shows key differences between two popular operating environments. As you can see, OS process management mechanisms differ syntactically and semantically. Addressing these platform variations in each application is difficult, tedious , error prone, and unnecessary because ACE provides the ACE_Process class. Class CapabilitiesThe ACE_Process class encapsulates the variation among different OS multiprocessing APIs in accordance with the Wrapper Facade pattern. This class defines uniform and portable methods whose capabilities enable applications to
The interface of the ACE_Process class is shown in Figure 8.2; its key platform-independent methods are outlined in the following table:
Figure 8.2. The ACE_Process Class Diagram
The ACE_Process class provides portable access to the common capability of spawning a new process and executing a new program image in the new process. Process management is one of the few functional areas, however, where wrapper facades can't encapsulate all the OS differences into one unified class that offers portability across the full range of OS platforms supported by ACE. For example, Sidebar 16 describes some key portability challenges associated with servers that use certain unique semantics of the POSIX fork() mechanism. Since UNIX is a key platform for networked applications, the ACE_Process class offers a number of methods that only work in a POSIX/UNIX environment. These methods are useful (indeed, necessary) in many design situations. To avoid confusion, they are listed in the table below, separate from the portable methods that ACE_Process offers.
ExampleThis example illustrates how to use ACE_Process to portably spawn a new process that runs a specified program image. The program we implement computes factorials "recursively" by
Although this is clearly not an efficient way to compute factorials, it illustrates the ACE_Process features concisely, as shown below. #include "ace/OS.h" #include "ace/Process.h" int main (int argc, char *argv[]) { ACE_Process_Options options; char *n_env = 0; int n; if (argc == 1) { // Top-level process. n_env = ACE_OS::getenv ("FACTORIAL"); n = n_env == 0 ? 0 : atoi (n_env); options.command_line ("%s %d", argv[0], n == 0 ? 10 : n); } else if (atoi (argv[l]) == 1) return 1; // Base case. else { n = atoi (argv[1]); options.command_line ("%s %d", argv[0], n - 1); } ACE_Process child; child.spawn (options); // Make the ''recursive'' call. child.wait (); return n * child.exit_code (); // Compute n factorial. } The call to ACE_Process::wait() will work regardless of whether the spawned process has finished before the call or not. If it has finished, the call completes immediately; if not, the method waits until the child process exits. This method is portable to all operating systems that support multiple processes. The example above presents the most basic and portable use of ACE_Process_Options : to specify the command line for a spawned program. The next section discusses why we need a separate options class and shows its range of capabilities. |
I l @ ve RuBoard |