Detailed wait and WAITPID functions

Source: Internet
Author: User

#include <sys/types.h>/*provides a definition of type pid_t*/#include<sys/wait.h>pid_t Wait (int*status) Once the process has called wait, it blocks itself immediately, 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 collects the child process information and destroys it and returns If no such sub-process is found, wait is 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, 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. The wait call routine:/*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 child process*/printf ("This is the child process with PID of%d/n", Getpid ()); Sleep (Ten);/*Sleep 10 seconds*/            }        Else{/*if the parent process*/PR=wait (NULL);/*to wait here*/printf ("I catched A child process with PID of%d/n"), PR); } exit (0);} Compile and run: $ gcc wait1.c-o wait1$./Wait1this isChild process with PID of1508I catched A child process with PID of1508It 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. 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, which we will describe in a later article), the return value at normal end, or the end of the signal. 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 normally exited, and if so, it returns a value other than 0 (note that, although the name is the same, here the parameter status is different from the wait unique argument---pointer to an integer status, 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, if the child process calls exit (5Exit, Wexitstatus (status) returns 5 if the child process calls exit (7), Wexitstatus (status) returns 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>Main () {intstatus;               pid_t PC,PR; PC=Fork (); if(pc<0)/*If an error occurs*/printf ("Error ocurred!/n"); Else if(pc==0){/*Child Process*/printf ("This is the child process with PID of%d./n", Getpid ()); Exit (3);/*child process returns 3*/        }        Else{/*Parent Process*/PR=wait (&status); if(wifexited (status)) {/*if wifexited returns a value other than 0*/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: $ gcc wait2.c-o wait2$./Wait2this isChild process with PID of1538. the child process1538Exit Normally.thereturnCode is 3The 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. Process synchronization: Sometimes, the parent process requires the result of the child process to perform the next operation, or the function of the child process is to provide the parent process with the next step of execution of the prerequisite (such as: the child process to establish a file, and the parent process to write data), the parent process must stop at a certain location, waiting for the child process to And if the parent process does not wait and execute directly, you can imagine that there will be great confusion. This situation is called synchronization between processes, and more accurately, this is a special case of process synchronization. Process synchronization is the coordination of more than 2 processes, so that they are arranged in order to execute sequentially. There is a more general approach to solving the process synchronization problem, which we will introduce later, but for the hypothetical scenario, it can be solved simply by using the wait system call. Take a look at the following procedure: #include<sys/types.h>#include<sys/wait.h>Main () {pid_t pc, PR; intstatus; PC=Fork (); if(pc<0) printf ("Error occured on forking./n"); Else if(pc==0){                /*the work of the child process*/Exit (0); }Else{               /*the work of the parent process*/PR=wait (&status); /*using the results of child processes*/}} This program is just an example, not really carry out, but it shows some problems, first of all, when the fork call succeeds, the parent-child process to do each thing, but when the work of the parent process is over, it needs to use the results of the child process, it stopped calling wait, until the end of the child process run, We then use the result of the child process to continue execution, which satisfactorily solves the process synchronization problem we proposed. The prototype of the WAITPID system call in the Linux function library is: #include<sys/types.h>/*provides a definition of type pid_t*/#include<sys/wait.h>pid_t waitpid (pid_t pid,int*status,intoptions) 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 detail: PID: From the parameter's name PID and type pid_t you can see that a process ID is required here.         But when the PID takes a different value, there are different meanings here. PID>0 o'clock, just wait for the process ID equal to the PID of the child process, no matter how many other child processes have been run to exit, as long as the specified child process has not ended, Waitpid will continue to wait. PID=-1 o'clock, wait for any one of the child processes to exit without any restrictions, at which time the waitpid and wait functions exactly the same. PID=0 o'clock, 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 o'clock, waits for any child process in the specified process group, the ID of the process group equals the absolute value of the PID. Options:options provides some additional options to control Waitpid, which currently supports only Wnohang and wuntraced two options in Linux, which is two constants that can be used with a"|"operators to connect them with, for example: Ret=waitpid (-1, Null,wnohang |wuntraced); If we do not want to use them, we can also set the options to 0, such as: Ret=waitpid (-1Null0If you call Waitpid with the Wnohang parameter, it will return immediately, even if no child process exits, and will not wait forever as wait. And the wuntraced parameter, because involves some tracking debugging aspect knowledge, in addition very few uses, here does not have the expense pen and ink, the interested reader may consult the related material on its own. Seeing here, the smart reader may have seen the clue: Wait is not a packaged waitpid? Yes, look.< kernel source directory >/include/unistd.h file 349-352 lines will find the following program segments:StaticInline pid_t Wait (int*Wait_stat) {    returnWaitpid (-1, Wait_stat,0);} return value and Error waitpid the return value is slightly more complicated than wait, there are 3 kinds of cases:1, WAITPID returns the process ID of the child process that was collected when the normal return;2returns 0 if the option Wnohang is set, while waitpid in the call finds No child processes that have been exited to collect;3, if an error occurs in the call, returns-1, the errno is 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>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 (Ten);/*Sleep 10 seconds*/Exit (0); }        /*if the parent process*/        Do{PR=waitpid (PC, NULL, Wnohang);/*using the Wnohang parameter, Waitpid will not wait here*/               if(pr==0){/*If a child process is not collected*/printf ("No Child exited/n"); Sleep (1); }        } while(pr==0);/*No child processes are collected, go back and try again*/        if(pr==pc) printf ("successfully get child%d/n", PR); Elseprintf ("some error occured/n");} Compile and run: $ cc WAITPID.C-o waitpid$./waitpidno Child Exitedno child Exitedno child Exitedno child Exitedno child Exitedno child exitedno Child Exitedno Ch ILD Exitedno child Exitedno child exitedsuccessfullyGetChild1526after 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. Tip: You can try to put a PR in the last example=waitpid (PC, NULL, Wnohang); Change to Pr=waitpid (PC, NULL,0), or pr=wait (NULL); see how the results of the operation change? (The modified result causes the parent process to block itself until a child process exits!) )

Detailed wait and WAITPID functions

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.