Exceptional Control Flow(4)

Process Control 

Obtaining Process IDs 

Each process has a unique positive (nonzero) process ID (PID).

The getpid function returns the PID of the calling process.

The getppid function returns the PID of its parent (i.e., the process that created the calling process). 

Creating and Terminating Processes 

From a programmer’s perspective, we can think of a process as being in one of three states: 

(1) Running. The process is either executing on the CPU or is waiting to be executed and will eventually be scheduled by the kernel. 

(2) Stopped. The execution of the process is suspended and will not be scheduled.

A process stops as a result of receiving a SIGSTOP, SIGTSTP, SIGTTIN, or SIGTTOU signal, and it remains stopped until it receives a SIGCONT signal, at which point it can begin running again.

(A signal is a form of software interrupt that is described in detail in Section 8.5.) 

 (3)Terminated. The process is stopped permanently. A process becomes termi- nated for one of three reasons: (1) receiving a signal whose default action is to terminate the process, (2) returning from the main routine, or (3) calling the exit function: 

The exit function terminates the process with an exit status of status. (The other way to set the exit status is to return an integer value from the main routine.) 

A parent process creates a new running child process by calling the fork function. 

The newly created child process is almost, but not quite, identical to the par- ent.

The child gets an identical (but separate) copy of the parent’s user-level virtual address space, including the text, data, and bss segments, heap, and user stack.

The child also gets identical copies of any of the parent’s open file descriptors, which means the child can read and write any files that were open in the parent when it called fork. The most significant difference between the parent and the newly created child is that they have different PIDs

The fork function is interesting (and often confusing) because it is called once but it returns twice:

once in the calling process (the parent), and once in the newly created child process.

In the parent, fork returns the PID of the child. In the child, fork returns a value of 0.

Since the PID of the child is always nonzero, the return value provides an unambiguous way to tell whether the program is executing in the parent or the child. 

Shared files. When we run the example program, we notice that both parent and child print their output on the screen.

The reason is that the child inherits all of the parent’s open files.

When the parent calls fork, the stdout file is open and directed to the screen.

The child inherits this file and thus its output is also directed to the screen. 

Reaping Child Processes 

When a process terminates for any reason, the kernel does not remove it from the system immediately.

Instead, the process is kept around in a terminated state until it is reaped by its parent.

When the parent reaps the terminated child, the kernel passes the child’s exit status to the parent, and then discards the terminated process, at which point it ceases to exist.

A terminated process that has not yet been reaped is called a zombie

If the parent process terminates without reaping its zombie children, the kernel arranges for the init process to reap them.

The init process has a PID of 1 and is created by the kernel during system initialization.

Long-running programs such as shells or servers should always reap their zombie children.

Even though zombies are not running, they still consume system memory resources

A process waits for its children to terminate or stop by calling the waitpid function. 

The waitpid function is complicated. By default (when options = 0), waitpid suspends execution of the calling process until a child process in its wait set terminates.  

If a process in the wait set has already terminated at the time of the call, then waitpid returns immediately

In either case, waitpid returns the PID of the terminated child that caused waitpid to return, and the terminated child is removed from the system. 

Determining the Members of the Wait Set 

The members of the wait set are determined by the pid argument: 

  • .  If pid > 0, then the wait set is the singleton child process whose process ID is equal to pid.

  • .  If pid = -1, then the wait set consists of all of the parent’s child processes. 

Modifying the Default Behavior 

The default behavior can be modified by setting options to various combinations of the WNOHANG and WUNTRACED constants:

(1) WNOHANG: Return immediately (with a return value of 0) if none of the child processes in the wait set has terminated yet.

The default behavior sus- pends the calling process until a child terminates.

This option is useful in those cases where you want to continue doing useful work while waiting for a child to terminate. 

(2) WUNTRACED: Suspend execution of the calling process until a process in the wait set becomes either terminated or stopped.

Return the PID of the terminated or stopped child that caused the return.

The default behavior returns only for terminated children.

This option is useful when you want to check for both terminated and stopped children. 

(3) WNOHANG|WUNTRACED: Return immediately, with a return value of 0, if none of the children in the wait set has stopped or terminated,

or with a return value equal to the PID of one of the stopped or terminated children. 

Checking the Exit Status of a Reaped Child 

If the status argument is non-NULL, then waitpid encodes status information about the child that caused the return in the status argument.  

The wait.h include file defines several macros for interpreting the status argument: 

(1) WIFEXITED(status): Returns true if the child terminated normally, via a call to exit or a return. 

(2) WEXITSTATUS(status): Returns the exit status of a normally terminated child. This status is only defined if WIFEXITED returned true

(3) WIFSIGNALED(status): Returns true if the child process terminated be- cause of a signal that was not caught.

(4) WTERMSIG(status): Returns the number of the signal that caused the child process to terminate.

This status is only defined if WIFSIGNALED(status) returned true

(5) WIFSTOPPED(status): Returns true if the child that caused the return is currently stopped

(6) WSTOPSIG(status): Returns the number of the signal that caused the child to stop. This status is only defined if WIFSTOPPED(status) returned true

Error Conditions 

If the calling process has no children, then waitpid returns −1 and sets errno to ECHILD.

If the waitpid function was interrupted by a signal, then it returns −1 and sets errno to EINTR. 

an example for waitpid function:

and notice that when all of the children have been reaped, the next call to waitpid returns −1 and sets errno to ECHILD.

example for waiting for pid in a certain order:

 

原文地址:https://www.cnblogs.com/geeklove01/p/9250703.html