孤儿进程
在Linux/Unix环境中,我们是通过fork函数来创建子进程的。创建完毕之后,父子进程独立运行,父进程无法预知子进程什么时候结束。通常情况下,子进程退出后,父进程会使用wait或waitpid函数进行回收子进程的资源,并获得子进程的终止状态。
但是,如果父进程先于子进程结束,则子进程成为孤儿进程。孤儿进程将被init进程(进程号为1)领养,并由init进程对孤儿进程完成状态收集工作。
因此,孤儿进程是没有父进程的进程,它在完成自己的工作退出之后,init进程将完成孤儿进程的善后工作,回收它的资源,因此孤儿进程并不会有什么危害。
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
pid = fork();
if (pid == 0) {
while (1) {
/* 子进程死循环,保证不死 */
printf("I am child, my parent pid = %d\n", getppid());
sleep(1);
}
} else if (pid > 0) {
/* 父进程睡眠3秒后退出 */
printf("I am parent, my pid is = %d\n", getpid());
sleep(3);
printf("------------parent going to die------------\n");
} else {
perror("fork");
return 1;
}
return 0;
}
僵尸进程
而如果子进程先于父进程退出,同时父进程太忙了,无瑕回收子进程的资源,子进程残留资源(PCB)存放于内核中,变成僵尸(Zombie)进程。
内核对于进程的退出有一套固定的机制,就是会释放该进程所有的资源,包括打开的文件,占用的内存等。但仍然有一部分信息残留在内核中,比如:进程号,退出状态,运行时间等。一般来说,父进程会调用wait或waitpid来获取子进程的退出状态,子进程的资源也随之释放。但如果父进程陷入死循环或没有调用wait/waitpid函数的话,那么子进程残留的信息将得不到释放,会一直占用内核资源。而内核的资源一般是非常宝贵的,因此如果产生大量的僵尸进程的话,将严重影响系统的性能,应避免僵尸进程的产生。
杀死僵尸进程的方法:
如其名,僵尸进程其实已经就是退出的进程,因此无法再利用kill命令杀死僵尸进程。僵尸进程的罪魁祸首是父进程没有回收它的资源,那我们可以想办法它其它进程去回收僵尸进程的资源,这个进程就是init进程。因此,我们可以直接杀死父进程,init进程就会很善良地把那些僵尸进程领养过来,并合理的回收它们的资源,那些僵尸进程就得到了妥善的处理了。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
pid = fork();
if (pid == 0) {
printf("I am child, my parent= %d, going to sleep 3s\n", getppid());
sleep(3);
printf("-------------child die--------------\n");
} else if (pid > 0) {
printf("I am parent, pid = %d, myson = %d, going to sleep 5s\n", getpid(), pid);
sleep(5);
system("ps -o pid,ppid,state,tty,command");
} else {
perror("fork");
return 1;
}
return 0;
}
---------------
码字不易,点个赞再走呗~
我是良许,世界500强外企 Linux 开发工程师,专业生产 Linux 干货。欢迎关注我的公众号「良许Linux」,回复「1024」获取最新最全的技术资料,回复「入群」进入高手如云技术交流群;提供永久免费 CSDN 资料下载服务。