一、孤儿进程
父进程运行结束,但子进程还在运行(未运行结束)的子进程就称为孤儿进程(Orphan Process)。
每当出现一个孤儿进程的时候,内核就把孤儿进程的父进程设置为 init ,而 init 进程会循环地 wait() 它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init 进程就会代表党和政府出面处理它的一切善后工作。
因此孤儿进程并不会有什么危害。
二、僵尸进程
进程终止,父进程尚未回收,子进程残留资源(PCB)存放于内核中,变成僵尸(Zombie)进程。
这样就会导致一个问题,如果进程不调用wait() 或 waitpid() 的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程,此即为僵尸进程的危害,应当避免。
上面描述了关于孤儿进程和僵尸进程的概念和可能造成的影响。下面以代码例子更加深入了解
1、正常场景
该场景会在父进程中通过waitpid等待回收子进程的资源,保证不会出现资源泄漏情况
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
pid_t ppid, childPid;
int status = 0;
system("ps -aux | grep forkTest");
printf("-------------------------\n");
ppid = fork();
if(ppid < 0)
{
perror("error in fork");
} else if (ppid == 0)
{
printf("this is in child process, child process pid:%d\n",getpid());
//sleep 3s and exit child process
sleep(30);
exit(0);
} else{
printf("this is in parent process, parent process pid:%d\n", getpid());
}
do{
childPid = waitpid(ppid, &status, WNOHANG);
if(childPid == 0)
{
printf("No child exited,ret=%d\n", childPid);
sleep(2);
}
}while(childPid == 0);
if(WIFEXITED(status))
printf("normal exited:%d\n",childPid);
if(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL)
printf("process killed by signal SIGKILL\n");
return 0;
}
2、僵尸进程
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
pid_t ppid;
ppid = fork();//创建进程
if(ppid < 0)
{
perror("error in fork");`在这里插入代码片`
} else if (ppid == 0) //ppid为0则为子线程
{
printf("this is in child process, child process pid:%d\n",getpid());
exit(0); //这里让子进程先退出,父进程没有回收子进程资源则会导致僵尸进程的出现
} else{ //ppid>0则为父线程
printf("this is in parent process, parent process pid:%d\n", getpid());
}
sleep(300); //这里sleep为了保证父进程后退出
return 0;
}
结果分析如下:
为了防止僵尸进程的出现,应该在父进程中回收子进程退出后的资源,可以使用wait或者waitpid回收资源
3、孤儿进程
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
pid_t ppid;
ppid = fork();//创建进程
if(ppid < 0)
{
perror("error in fork");
} else if (ppid == 0) //ppid为0则为子线程
{
printf("this is in child process, child process pid:%d\n",getpid());
sleep(30); //这里睡眠30s为了保证子进程后于父进程退出
exit(0);
} else{ //ppid>0则为父线程
printf("this is in parent process, parent process pid:%d\n", getpid());
}
return 0;
}
该种情况会出现孤儿进程,但该孤儿进程会被系统init接管保证资源释放的工作,故孤儿进程并没有什么危害。