🌏博客主页:PH_modest的博客主页
🚩当前专栏:Linux跬步积累
💌其他专栏:
🔴 每日一题
🟡 C++跬步积累
🟢 C语言跬步积累
🌈座右铭:广积粮,缓称王!
文章目录
- 僵尸进程
- 基础概念
- 僵尸进程的危害
- 孤儿进程
- 基础概念
僵尸进程
基础概念
进程状态这篇博客中讲到,一个进程若是在等待退出信息被读取,那么我们称该进程处于僵尸状态。而处于僵尸状态的进程被称之为僵尸进程。
例如,下面的代码,fork函数创建的子进程会在打印5次信息后退出,而父进程是个死循环,会一直打印。这时就满足了子进程退出,父进程还在运行的情况,但是父进程并没有读取到子进程的退出信息,所以子进程会处于僵尸状态。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("I am running...\n");
pid_t id = fork();
if(id == 0){ //child
int count = 5;
while(count){
printf("I am child...PID:%d, PPID:%d, count:%d\n", getpid(), getppid(), count);
sleep(1);
count--;
}
printf("child quit...\n");
exit(1);
}
else if(id > 0){ //father
while(1){
printf("I am father...PID:%d, PPID:%d\n", getpid(), getppid());
sleep(1);
}
}
else{ //fork error
}
return 0;
}
运行该代码后,我们可以通过以下监控脚本,每隔一秒对该进程的信息进行检测。
[hph@hecs-345360 demo-8-6]$ while :; do ps axj | head -1 && ps axj | grep proo "######################";sleep 1;done
检测后发现,当子进程退出后,子进程的状态就变成了僵尸状态。
僵尸进程的危害
- 僵尸进程的退出状态必须一直维持下去,因为它要告诉其父进程相应的退出信息。可是父进程一直不读取,那么子进程也就一直处于僵尸状态。
- 僵尸进程的退出信息被保存在 task_struct(PCB)当中,僵尸状态一直不退出,那么PCB就一直需要进行维护。
- 若是一个父进程创建了很多子进程,但都不进行回收,那么就会造成资源浪费,因为数据结构对象本身就要占用内存。
- 僵尸进程申请的资源无法进行回收,那么僵尸进程越多,实际可用的资源就越少,也就是说,僵尸进行会导致内存泄漏。
孤儿进程
基础概念
在Linux当中的进程关系大多数是父子关系,若子进程先退出而父进程没有对子进程的退出信息进行读取,那么我们称该进程为僵尸进程。但若是父进程先退出,那么将来子进程进入僵尸状态时就没有父进程对其进行处理,此时该子进程就称之为孤儿进程。
若是一直不处理孤儿进程的退出信息,那么孤儿进程就会一直占用资源,此时就会造成内存泄漏。因此,当出现孤儿进程的时候,孤儿进程会被1号init进程领养,此后当孤儿进程进入僵尸状态时就由init进程进行回收处理。
例如,对于以下代码,fork函数创建的子进程会一直打印信息,而父进程在打印5次信息后会退出,此时该子进程就变成了孤儿进程。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("I am running...\n");
pid_t id = fork();
if(id == 0){ //child
int count = 5;
while(1){
printf("I am child...PID:%d, PPID:%d\n", getpid(), getppid(), count);
sleep(1);
}
}
else if(id > 0){ //father
int count = 5;
while(count){
printf("I am father...PID:%d, PPID:%d, count:%d\n", getpid(), getppid(), count);
sleep(1);
count--;
}
printf("father quit...\n");
exit(0);
}
else{ //fork error
}
return 0;
}
观察代码运行结果,在父进程为退出时,子进程的PPID就是父进程的PID,而父进程退出之后,子进程的PPID就变成了1,即子进程被1号进程领养了。