Author: Lxmuyu
Links: Wait, waitpid
Wait
1.1 Introduction
The wait function requires a header file:
#include <sys/types.h>
#include <sys/wait.h>
Wait function prototype:
pid_t Wait (int *status);
Once the process has called wait, it immediately blocks itself, and the wait automatically parses if a child process of the current process has exited, and if it finds such a child process that has become a zombie, wait will collect information about the child process and destroy it and return it, if no such child process is found. Wait will always be stuck here until one appears.
The parameter status is used to hold some state when the collection process exits, which is a pointer to type int. But if we don't care about how this subprocess dies, we just want to get rid of this zombie process (and in most cases we will), we can set this parameter to NULL, just like this:
PID = Wait (NULL);
If successful, wait returns the process ID of the child process being collected, and if the calling process does not have child processes, the call fails, and wait returns 1 while errno is set to Echild.
1.2 Combat
Let us use an example to apply the wait call, the program used in the system call fork, if you are not familiar with this or have forgotten, please refer to the use of the fork function.
/* WAIT1.C */
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main ()
{
pid_t PC,PR;
PC = fork ();
if (PC < 0)/* If error occurs */
printf ("Error ocurred!\n");
else if (PC = = 0)/* If it is a child process */
{
printf ("This is a child process with PID of%d\n", Getpid ());
Sleep (10); /* Sleep 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 1508I
#catched a child process with PID of 1508
It is noticeable that there is a wait time of 10 seconds before the result of the 2nd line is printed, which is the time we set to let the child process sleep, and only when the child process wakes up from sleep, it can exit normally, and it can be captured by the parent process. In fact, we don't care how long the child process sleeps, the parent process waits, and if the reader is interested, try to modify the value yourself to see what happens.
1.3 parameter Status
If the value of the parameter status is not null,wait, the state of the process exit is fetched and entered, which is an integer value (int), indicating whether the child process exits normally or is abnormally terminated (a process can also be signaled by another process), and the return value at the normal end. or by which signal to end the information. Since this information is stored in a different bits of integers, it can be cumbersome to read in a regular way, and people have designed a special macro to do the work, so let's take a look at the two most common ones:
1,wifexited (status) This macro is used to indicate whether a child process is exiting normally, and if so, it returns a value other than 0. (Note that, although the name is the same, the parameter status here differs from the wait-only argument-pointer status to an integer, but the integer that the pointer points to, remember not to confuse it.) )
2,wexitstatus (status) When Wifexited returns a value other than 0, we can use this macro to extract the return value of the child process, and if the child process calls exit (5), Wexitstatus (status) returns 5 if the child process calls exit (7), Wexitstatus (status) will return 7. Note that if the process does not exit normally, that is, wifexited returns 0, this value is meaningless.
Here's an example of what we just learned:
/* WAIT2.C */
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main ()
{
int status;
pid_t PC,PR;
PC = fork (); /* Call the fork function */
if (PC < 0)/* If error occurs */
printf ("Error ocurred!\n");
else if (PC = = 0)/* Child process */
{
printf ("This is a child process with PID of%d.\n", Getpid ());
Exit (3); /* Child Process returns 3 */
}
else/* Parent Process */
{
PR = Wait (&status);
if (wifexited (status))
{
printf ("The child process%d exit normally.\n", PR);
printf ("The Return code is%d.\n", Wexitstatus (status));
}
else/* If wifexited returns 0 */
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 Child process 1538 exit abnormally.
The parent process accurately captures the return value of the child process by 3 and prints it out.
Of course, there are more than two macros to handle the exit status of the process, but most of them are rarely used in normal programming, and are not wasted here, and interested readers can refer to the Linux man pages themselves to understand their usage.
Waitpid
2.1 Introduction
The WAITPID system calls the desired header file in the Linux function library:
#include <sys/types.h>
#include <sys/wait.h>
The prototype of the WAITPID system call in the Linux libraries is:
pid_t waitpid (pid_t pid,int *status,int options);
In essence, system calls Waitpid and wait are exactly the same, but the waitpid has more than two user-controlled parameter PID and options, which gives us another more flexible way to program. Let's take a look at these two parameters in more detail:
PID
As can be seen from the parameter's name PID and type pid_t, a process ID is required here. But when the PID takes a different value, there are different meanings here.
Pid>0, wait for the process ID equal to the PID of the child process, no matter how many of the other already run the end exit, as long as the specified child process is not finished, Waitpid will continue to wait.
Pid=-1, wait for any child process to exit without any restrictions, at which time waitpid and wait do exactly the same.
Pid=0, wait for any child process in the same process group, and Waitpid will not ignore it if the child process has joined another process group.
Pid<-1 waits for any child process in a specified process group, the ID of the process group equals the absolute value of the PID.
Options
Options provides some additional option to control Waitpid, which is currently supported only in Linux
WnohangAnd
wuntracedTwo options, this is a two constant, you can use the "|" Operators to connect them together, such as:
Ret=waitpid ( -1,null,wnohang | wuntraced);
If we do not want to use them, we can also set options to 0, such as:
Ret=waitpid ( -1,null,0);
If you call Waitpid with the Wnohang parameter, it will return immediately if there are no terminated processes, and will not wait as long as wait.
The wuntraced parameter, if the child process enters a paused execution, returns immediately, but the terminating state is ignored.
Seeing here, the clever reader may have discerned that--wait is not a packaged waitpid? Yes, look at the < kernel source directory >/include/unistd.h file 349-352 lines will find the following program segment:
Static inline pid_t Wait (int * wait_stat) {return waitpid ( -1,wait_stat,0);}
2.2 Return values and errors
The return value of the waitpid is slightly more complex than wait, with a total of 3 cases:
When returned normally, WAITPID returns the process ID of the child process that was collected, or 0 if the option Wnohang was set and waitpid found that no child processes that were exited could be collected, or 1 if an error occurred in the call. The errno is then set to the corresponding value to indicate the error, when the PID indicates that the child process does not exist, or the process exists, but not the child process of the calling process, Waitpid will be returned with an error, when errno is set to Echild;
/* WAITPID.C */
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main ()
{
pid_t pc, PR;
PC = fork ();
if (PC < 0)/* If fork is wrong */
printf ("Error occured on forking.\n");
else if (PC = = 0)/* If it is a child process */
{
Sleep (10); /* Sleep 10 seconds */
Exit (0);
}
else/* If it is a parent process */
Do
{
PR = waitpid (PC, NULL, Wnohang); /* Using the Wnohang parameter, Waitpid will not wait here */
if (pr = = 0)/* If no child process is collected */
{
printf ("No child exited\n");
Sleep (1);
}
}
while (pr = = 0); /* No child process is collected, go back to try */
if (pr = = PC)
printf ("Successfully get child%d\n", PR);
Else
printf ("Some error occured\n");
}
Compile and run:
#gcc 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 by the parent process, the retired child process is finally collected.
Because this is just an example program, the inconvenience is too complicated to write, so we let the parent process and the child process sleep for 10 seconds and 1 seconds respectively, representing them for 10 seconds and 1 seconds of work. Parent-child processes have work to do, and parents take advantage of the work of a short interval to see if the child process exits, such as the exit to collect it.
Reprint--wait Waitpid Explanation