Asynchronous processes execute independent of each other. Process A runs until completion without any regard to process B. Asynchronous processes may or may not have a parent “child relationship. If process A creates process B, they can both execute independently but at some point the parent retrieves the exit status of the child. If they do not have a parent “child relationship, they may share the same parent. Table 3-7. Information Contained in struct rusage
Asynchronous processes may execute serially , simultaneously, or overlap. These scenarios are depicted in Figure 3-12. In case 1, process A runs until completion, process B runs until completion, then process C runs until completion. This is serial execution of these processes. Case 2 depicts simultaneous execution of processes. Processes A and B are active processes. While process A is running, process B is sleeping. At some point both processes are sleeping. Process B awakens before process A, process A awakens, and now both processes are running at the same time. This shows that asynchronous processes may execute simultaneously only during certain intervals of their execution. In case 3, the execution of processes A and B overlaps. Figure 3-12. Possible scenarios of asynchronous and synchronous processes.
Asynchronous processes may share resources like a file or memory. This may or may not require synchronization or cooperation of the use of the resource. If the processes are executing serially (case 1), then they will not require any synchronization. For example, all three processes, A, B, and C, may share a global variable. Process A writes to the variable before it terminates, then when process B runs, it reads the data stored in the variable and before it terminates it writes to the variable. When it runs, process C reads data from the variable. But in cases 2 and 3, the processes may attempt to modify the variable at the same time, thus requiring synchronization of its use. For our purposes, we define synchronous processes as processes with inter-leaved execution, one process suspends its execution until another process finishes. For example, process A, the parent process, executes and creates process B, the child process. Process A suspends its execution until process B runs until completion. When process B terminates, its exit code is placed in the process table. Process A is informed that process B has terminated . Process A can resume additional processing, then terminate or it can immediately terminate. Process A and process B are synchronous processes. Figure 3-12 contrasts synchronous and asynchronous execution of processes A and B. 3.9.1 Synchronous and Asynchronous Processes Created with fork() , exec () , system() , and posix_spawn() FunctionsProcesses created by fork() , fork-exec , and posix_spawn() functions will create asynchronous processes. When using the fork() function, the parent process image is duplicated . Once the child process has been created, the function returns to parent the child's PID and a return value of , indicating process creation was successful. The parent does not suspend execution; both processes continue to execute independently from the statement immediately preceding the fork() . Child processes created using the fork-exec combination initializes the child's process image with a new process image. The exec() functions do not return to the parent process unless the initialization was not successful. The posix_spawn() functions create the child process images and initialize it within one function call. The PID is returned to the posix_spawn() as well as a return value indicating if the process was spawned successfully. After posix_spawn() returns, both processes are executing at the same time. Processes created by the system() function will create synchronous processes. A shell is created that executes the system command or executable file. The parent process is suspended until the child process terminates and the system() call returns. 3.9.2 The wait() Function CallAsynchronous processes can suspend execution until a child process terminates by executing the wait() system call. After the child process terminates, a waiting parent process collects the child's exit status, which prevents zombied processes. The wait() function obtains the exit status from the process table. The status parameter points to a location that contains the exit status of the child process. If the parent process has more than one child process and several of them have terminated, the wait() function only retrieves the exit status for one child process from the process table. If the status information is available before the execution of the wait() function, the function will return immediately. If the parent process does not have any children, the function returns with an error code. The wait() function can also be called when the calling process is to wait until a signal is delivered then perform some signal handling action.
The waitpid() function is the same as wait() except it takes an additional parameter, pid . The pid parameter specifies a set of child processes for which the exit status is retrieved. Which processes are in the set is determined by the value of pid :
The options parameter determines how the wait should behave and can have the value of the following constants defined in the header <sys/wait.h> :
These constants can be logically OR'ed and passed as the options parameter (e.g., WCONTINUED WUNTRACED ). Both functions return the PID of the child process whose exit status was obtained. If the value stored in status is , then the child process has terminated under these conditions:
Table 3-8 lists the macros in which the value of the exit status can be evaluated. Table 3-8. Macros in Which the Value of the Exit Status Can be Evaluated
|