catalogue
2.1: the status parameter of the wait function is null.
2.2: the status parameter of the wait function is not empty.
1. The exit state of the child process is not collected by the parent process and becomes a dead process (zombie process)
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() { pid_t pid; int cnt = 0; pid = vfork(); if(pid > 0){ while(1){ printf("this is father print: pid = %d \n",getpid()); printf("cnt = %d\n",cnt); sleep(1); } } else if(pid == 0){ while(1){ printf("this is child print: pid = %d \n",getpid()); cnt++; if(cnt == 3){ exit(0); } sleep(1); } } return 0; }
2. The exit status of the child process is collected by the parent process and the wait function is called
NAME
wait, waitpid, waitid - wait for process to change state
SYNOPSIS
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
While waiting:
- Blocking occurs if all of its child processes are still running.
- If a child process has been terminated and is waiting for the parent process to obtain its termination status, the termination status of the child process will be returned immediately.
- If it does not have any child processes, an error is returned immediately.
status parameter:
Is an integer pointer
Non empty:
The exit state of a child process is stored in the address it points to
Empty:
Don't care about exit status
2.1: the status parameter of the wait function is null.
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() { pid_t pid; int cnt = 0; pid = fork(); if(pid > 0){ wait(NULL); while(1){ printf("this is father print: pid = %d \n",getpid()); printf("cnt = %d\n",cnt); sleep(1); } } else if(pid == 0){ while(1){ printf("this is child print: pid = %d \n",getpid()); cnt++; if(cnt == 5){ exit(0); } sleep(1); } } return 0; }
Conclusion:
Both parent and child processes are running normally.
2.2: the status parameter of the wait function is not empty.
When the status parameter of the wait function is not empty and we want to check the status code of the termination status of which child process is returned
We need the following table: check the macro of the termination status returned by wait and waitpid to parse the status code.
macro | explain |
WIFEXITED(status) | True if it is the status returned by the normal termination child process. In this case, execute WEXITSTATUS(status), and transfer the child process to exit_ Exit or_ The lower 8 bits of the exit parameter |
WIFSIGNALED(status) | If it is the status returned by the child process of abnormal termination, it is true (receiving a signal that is not captured). In this case, WTERMSIG(status) can be executed to take the signal number that terminates the child process. In addition, some implementations define the macro WCOREDUMP(status), which returns true if a core file that terminates the process has been generated |
WIFSTOPPED(status) | True if it is the return status of the currently suspended child process. In this case, execute WSTOPSIG(status) and take the signal number that suspends the child process |
WIFCONTINUED(status) | True if the child process that has continued after the job control is suspended returns to the state. (XSI extension for POSIX.1; for waitpid only.) |
The following code calls the first macro, # WEXITSTATUS(status), which normally terminates the status returned by the child process. It is true:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() { pid_t pid; int cnt = 0; int status = 10; pid = fork(); if(pid > 0){ wait(&status); printf("child quit,child status = %d\n",WEXITSTATUS(status)); while(1){ printf("cnt = %d\n",cnt); printf("this is father print: pid = %d \n",getpid()); sleep(1); } } else if(pid == 0){ while(1){ printf("this is child print: pid = %d \n",getpid()); cnt++; if(cnt == 5){ exit(3); } sleep(1); } } return 0; }
3. (difference between wait and waitpid) wait blocks the caller. Waitpid has an option to make the caller not block.
Waitpid function prototype: pid_t waitpid(pid_t pid, int *status, int options);
The functions of pid parameters in waitpid function are explained as follows:
pid == –1 | Wait for any child process. In this respect, waitpid is equivalent to wait. |
pid > 0 | Wait for a child process whose process ID is equal to pid. |
pid == 0 | Wait for any child process whose group ID is equal to the calling process group ID. |
pid < –1 | Wait for any child process whose group ID is equal to the absolute value of pid. |
options constant of waitpid: (the second one is used more often, without blocking)
constant | explain |
WCONTINUED | If the implementation supports job control, if any sub process specified by pid has continued after suspension, but its status has not been reported, its status will be returned |
WNOHANG | If the child process specified by pid is not immediately available, waitpid is not blocked, and its return value is 0 |
WUNTRACED | If an implementation supports job control, and any child process specified by pid has been suspended, and its status has not been reported since the suspension, its status is returned. The WIFSTOPPED macro determines whether the return value corresponds to a suspended child process |
The options constant of waitpid: the second kind of WNOHANG is non blocking. Write a code demo as follows:
Conclusion: when the parent process waits with waitpid without blocking, the child process is (zombie process). Both processes are running
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() { pid_t pid; int cnt = 0; int status = 10; pid = fork(); if(pid > 0){ //wait(&status); waitpid(pid,&status,WNOHANG); printf("child quit,child status = %d\n",WEXITSTATUS(status)); while(1){ printf("cnt = %d\n",cnt); printf("this is father print: pid = %d \n",getpid()); sleep(1); } } else if(pid == 0){ while(1){ printf("this is child print: pid = %d \n",getpid()); cnt++; if(cnt == 5){ exit(3); } sleep(1); } } return 0; }
4. Orphan process
If the parent process does not wait for the child process to exit, it will end its "life" before the child process. At this time, the child process is called an orphan process
Linux avoids too many orphan processes in the system. init process (an initialization process of the system, its pid number is 1) takes in the orphan process and becomes the parent process of the orphan process.
The code demo demonstrates that the init process takes in orphan processes, as follows:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() { pid_t pid; int cnt = 0; int status = 10; pid = fork(); if(pid > 0){ printf("this is father print: pid = %d \n",getpid()); } else if(pid == 0){ while(1){ printf("this is child print: pid = %d,my father pid = %d \n",getpid(),getppid()); cnt++; if(cnt == 5){ exit(3); } sleep(1); } } return 0; }