Linux Process Control-Wait ()

Source: Internet
Author: User
(Switch) Linux Process Control-Wait ()
# Include <sys/types. h>/* define the pid_t type */
# Include <sys/Wait. H>
Pid_t wait (int * Status)

Once a process calls wait, it immediately blocks itself. Wait automatically analyzes whether a sub-process of the current process has exited. If it finds such a sub-process that has become a zombie, wait will collect information about this sub-process and destroy it completely and return it. If such a sub-process is not found, wait will be blocked until one appears.
The status parameter is used to save some statuses when the collection process exits. It is a pointer to the int type. But if we don't care about how this sub-process died, we just want to destroy it (in fact, in most cases, we will think like this ), we can set this parameter to null, as shown below:

pid = wait(NULL);

If the call succeeds, wait returns the ID of the collected sub-process. If the call process does not have a sub-process, the call fails. In this case, wait returns-1 and errno is set to echild.


Let's use an example to apply the wait call:

/* Wait1.c */
# Include <sys/types. h>
# Include <sys/Wait. H>
# Include <unistd. h>
# Include <stdlib. h>
Main ()
{
Pid_t PC, PR;
PC = fork ();
If (Pc <0)/* if an error occurs */
Printf ("error ocurred! \ N ");
Else if (Pc = 0) {/* if it is a sub-process */
Printf ("this is child process with PID of % d \ n", getpid ());
Sleep (10);/* sleep for 10 seconds */
}
Else {/* if it is a parent process */
PR = wait (null);/* Wait here */
Printf ("I catched a child process with PID of % d \ n"), Pr );
}
Exit (0 );
}


Compile and run:

$ cc wait1.c -o wait1
$ ./wait1
This is child process with pid of 1508
I catched a child process with pid of 1508

We can obviously note that there is a waiting time of 10 seconds before the results of the first row are printed. This is the time we set for the sub-process to sleep. Only the sub-process wakes up from its sleep, it can exit normally and be captured by the parent process. In fact, no matter how long the sub-process sleeps, the parent process will keep waiting. If you are interested, you can try to modify the value by yourself, see what results will appear.

Parameter status:

If the value of the status parameter is not null, wait will take out the status of the sub-process and store it in it. This is an integer (INT ), it indicates whether the sub-process Exits normally or is ended abnormally (a process can also be ended by another process with a signal, which will be introduced in future articles ), and the return value at the normal end, or information about which signal is terminated. Because the information is stored in different binary bits of an integer, It is very troublesome to read it using the conventional method. People have designed a special macro (macro) to complete this work, next, let's take a look at two of the most common ones:

1. The wifexited (Status) macro is used to indicate whether the sub-process Exits normally. If yes, it returns a non-zero value.

(Please note that, although the name is the same, the parameter status here is not the only parameter of wait -- the pointer to the integer status, but the integer pointed to by the pointer. Remember not to confuse it .)

2. wexitstatus (Status) When wifexited returns a non-zero value, we can use this macro to extract the return value of the sub-process. If the sub-process calls exit (5) to exit, wexitstatus (Status) 5 is returned. If the sub-process calls exit (7), wexitstatus (Status) returns 7. Note that if the process does not exit normally, that is, if wifexited returns 0, this value is meaningless.

The following is an example of what we just learned:

/* Wait2.c */
# Include <sys/types. h>
# Include <sys/Wait. H>
# Include <unistd. h>
Main ()
{
Int status;
Pid_t PC, PR;
PC = fork ();
If (Pc <0)/* if an error occurs */
Printf ("error ocurred! \ N ");
Else if (Pc = 0) {/* sub-process */
Printf ("this is child process with PID of % d. \ n", getpid ());
Exit (3);/* the sub-process returns 3 */
}
Else {/* parent process */
PR = wait (& status );
If (wifexited (Status) {/* If wifexited returns a non-zero value */
Printf ("the child process % d exit normally. \ n", Pr );
Printf ("The return code is % d. \ n", wexitstatus (Status ));
} Else/* If wifexited returns zero */
Printf ("the child process % d exit abnormally. \ n", Pr );
}
}

Compile and run:

$ cc wait2.c -o wait2
$ ./wait2
This is child process with pid of 1538.
the child process 1538 exit normally.
the return code is 3.

The parent process accurately captures the returned value 3 of the child process and prints it out.

Of course, there are more than two macros that process exit state, but most of them are rarely used in normal programming, so it is not a waste of space here, interested readers can refer to Linux man pages to learn about their usage.

Process Synchronization:

Sometimes, the parent process requires the calculation result of the child process to perform the next operation, or the sub-process function is a prerequisite for the parent process to perform the next step (for example, the sub-process creates a file, the parent process writes data). At this time, the parent process must stop at a certain position and wait until the child process finishes running. If the parent process runs directly without waiting, you can imagine that, there will be great confusion. This situation is called synchronization between processes. More accurately, this is a special case of process synchronization. Process Synchronization is to coordinate more than two processes so that they can be executed in order. There are more common methods to solve the process synchronization problem. We will introduce it later, but we can simply use the wait system to call this situation. Please refer to the following procedure:

# Include <sys/types. h>
# Include <sys/Wait. H>
Main ()
{
Pid_t PC, PR;
Int status;

PC = fork ();

If (Pc <0)
Printf ("error occured on forking. \ n ");
Else if (Pc = 0 ){
/* Sub-process work */
Exit (0 );
} Else {
/* Work of the parent process */
PR = wait (& status );
/* Use sub-process results */
}
}

This program is just an example and cannot be used for execution, but it illustrates some problems. First, when the fork call is successful, the Parent and Child processes perform various tasks separately, however, when the work of the parent process has come to an end and the sub-process results need to be used, it will stop and call wait until the sub-process stops running and then continue to execute with the sub-process results, in this way, we have successfully solved the problem of process synchronization.





The prototype of waitpid system calling in the Linux function library is:

# Include <sys/types. h>/* define the pid_t type */
# Include <sys/Wait. H>
Pid_t waitpid (pid_t PID, int * status, int options)

In essence, the functions of the system call waitpid and wait are exactly the same, but the waitpid has two more user-controlled parameters PID and options, this provides us with a more flexible way of programming. The following two parameters are described in detail:

PID

From the parameter name PID and type pid_t, we can see that what is needed here is a process ID. But when the PID gets different values, it has different meanings here.

  1. When the PID is greater than 0, only the child process whose process ID is equal to the PID is waiting. No matter how many other child processes have ended and exited, as long as the specified child process has not ended, waitpid will keep waiting.
  2. When pid =-1, wait for any sub-process to exit without any restrictions. At this time, waitpid and wait play the same role.
  3. When pid = 0, wait for any sub-process in the same process group. If the sub-process has been added to another process group, waitpid will not ignore it.
  4. PID <-1, wait for any sub-process in a specified process group, the ID of this process group is equal to the absolute value of PID.

Options

Options provides some additional options to control waitpid. Currently, only the wnohang and wuntraced options are supported in Linux. These two constants can be connected using the "|" operator, for example:

ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);

If you do not want to use them, you can set options to 0, for example:

ret=waitpid(-1,NULL,0);

If the wnohang parameter is used to call waitpid, even if no sub-process exits, it will return immediately and will not wait forever like wait.

However, the wuntraced parameter involves some tracking and debugging knowledge and is rarely used. There is not much to worry about here. Interested readers can check the relevant materials on their own.

As you can see, smart readers may already see the clues-isn't wait a packaged waitpid? Check the <kernel source code directory>/include/unistd. h file 349-352 to find the following program segments:

static inline pid_t wait(int * wait_stat)
{
return waitpid(-1,wait_stat,0);
}


1.9.2 returned values and errors

The return value of waitpid is slightly more complex than that of wait. There are three cases:

  1. When the returned result is normal, waitpid returns the ID of the collected sub-process;
  2. If the wnohang option is set, and waitpid in the call finds that no child process has exited to collect data, 0 is returned;
  3. If an error occurs in the call,-1 is returned. errno is set to a value to indicate the error;

When the sub-process indicated by the PID does not exist or the process exists but is not a sub-process that calls the process, waitpid will return an error, and errno is set to echild;

/* Waitpid. C */
# Include <sys/types. h>
# Include <sys/Wait. H>
# Include <unistd. h>
Main ()
{
Pid_t PC, PR;

PC = fork ();
If (Pc <0)/* If fork fails */
Printf ("error occured on forking. \ n ");
Else if (Pc = 0) {/* if it is a sub-process */
Sleep (10);/* sleep for 10 seconds */
Exit (0 );
}
/* If it is a parent process */
Do {
PR = waitpid (PC, null, wnohang);/* The wnohang parameter is used, and waitpid will not wait here */
If (Pr = 0) {/* If the sub-process is not collected */
Printf ("No child exited \ n ");
Sleep (1 );
}
} While (Pr = 0);/* If the sub-process is not collected, go back and try again */
If (Pr = pc)
Printf ("successfully get child % d \ n", Pr );
Else
Printf ("some error occured \ n ");
}


Compile and run:

$ cc waitpid.c -o waitpid
$ ./waitpid
No child exited
No child exited
No child exited
No child exited
No child exited
No child exited
No child exited
No child exited
No child exited
No child exited
successfully get child 1526


After 10 failed attempts, the parent process finally collected the exited child process.

Because this is just an example program, it is inconvenient to write too complicated, so we let the Parent and Child processes sleep for 10 seconds and 1 second, respectively, it means that they work for 10 seconds and 1 second respectively. Both parent and child processes have work to do. The parent process uses the short interval of work to check whether the child process exits. If the child process exits, it is collected.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.