1.为什么要等待子进程退出
父进程等待子进程退出 并收集子进程的退出状态。子进程退出状态不被收集,变成僵死进程(僵尸进程)。
2.相关函数(wait()、waitpid())
区别: wait使调用者阻塞,waitpid有一个选项,可以使调用者不阻塞。
wait()代码实现:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main (int argc, char *argv[])
{
int cnt = 0;
int status = 10;
pid_t pid;
pid = fork();
if (pid > 0){
wait(&status);
printf("the status of the child exits is %d\n", WEXITSTATUS(status)); //通过WEXITSTATUS()可以解析出子进程退出状态码,也就是exit()括号内的数字
while(1){
printf("cnt = %d\n", cnt);
printf("this is parent pid: %d\n", getpid());
sleep(1);
}
}
else if(pid == 0){
while(1){
printf("this is child pid: %d\n", getpid());
sleep(1);
cnt++;
if (cnt == 3){
exit(5);
}
}
}
return 0;
}
运行结果:
waitpid()代码实现:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main (int argc, char *argv[])
{
int cnt = 0;
int status = 10;
pid_t pid;
pid = fork();
if (pid > 0){
//pid_t wait(int *wstatus);
//pid_t waitpid(pid_t pid, int *wstatus, int options);
waitpid(pid, &status, WNOHANG); //WNOHANG表示父进程不阻塞等待子进程退出再运行,父子进程一起竞争cpu
printf("the status of exit is %d\n", WEXITSTATUS(status));
while(1){
printf("cnt = %d\n", cnt);
printf("this is parent pid: %d\n", getpid());
sleep(1);
}
}
else if(pid == 0){
while(1){
printf("this is child pid: %d\n", getpid());
sleep(1);
cnt++;
if (cnt == 3){
exit(5);
}
}
}
return 0;
}
运行结果:
可以看出,在非阻塞的状态下,是无法解析出退出状态码,父子进程存在竞争关系
status参数: 是一个整型数指针
非空: 子进程退出状态放在它所指向的地址中。
空: 不关心退出状态。
3.孤儿进程
父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程叫做孤儿进程。
Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程。
代码实现:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
pid_t pid;
pid = fork();
if (pid > 0){
printf("this is parent pid: %d\n", getpid()); //在子进程结束前,父进程执行一次后结束进程,这是子进程就是孤儿进程了
}
else if(pid == 0){
while(1){
printf("this is child pid: %d\n", getpid());
sleep(1);
}
}
return 0;
}
运行结果: