什么是僵死进程?
当子进程先于父进程结束,父进程没有获取子进程的退出码,此时子进程变成僵死进程.
简而言之,就是子进程先结束,并且父进程没有获取它的退出码;
那么僵死进程产生的原因或者条件就是:子进程先于父进程结束,并且父进程没有获取子进程的退出码;
父进程执行7次,子进程改为3次;就能观察到僵死进程(放到后台运行&,ps -f);
- #include
- #include
- #include
- #include
-
- int main()
- {
- char *s=NULL;
- int n=0;//控制父子进程执行的次数;
-
- pid_t id=fork();
- assert(id!=-1);
-
- if(id==0)//子进程
- {
- s="child";
- n=3;
- }
- else//父进程
- {
- s="parent";
- n=7;
- }
- //父子进程
- int i=0;
- for(;i
- {
- printf("s=%s\n",s);
- sleep(1);
- }
- exit(0);
- }
4.处理僵死进程
(1)父进程先结束(子进程会变成孤儿进程,孤儿进程会被收养(红帽子是init(pid==1)收养孤儿进程,Unbuntu是操作系统指定了一个进程));
(2)父进程调用wait()方法获取子进程的退出码;
本质:都是调用了wait方法;
代码演示:
方法一:父进程先结束//就是把父进程的n=3,子进程的n=7即可;
方法二:显示的调用wait:
- else
- {
- s="parent";
- n=7;
- int val=0;
- wait(&val);
- printf("val=%d\n",val);
- }
但是两种方法都有区别:就是父进程调用wait会阻塞,等子进程执行完之后,父进程才会去执行;
5.处理僵死进程的意义;
僵死进程的坏处:白白消耗内存;(讲服务器代码的时候会演示)
Linux内核设计与实现27页;
6.退出码
改代码:exit(3);
执行显示val=768;
man 2 wait
WIFEXITED:正常退出的状态;
WEXITSTATUS:获取退出码;
- else//父进程
- {
- s="parent";
- n=7;
- int val=0;
- wait(&val);
- if(WIFEXITED(val))
- {
- printf("val=%d\n",WEXITSTATUS(val));
- }
- }
将退出码设为exit(3),未使用WIFEXITED(),WEXITSTATUS()之前。结果如下:
使用WIFEXITED(),WEXITSTATUS()。结果如下:
7.避免僵死进程的方法总结
1)父进程先结束;
2)父进程调用wait()方法获取子进程的退出码;
其实两种处理僵死进程的方法本质都是一样的,都调用了wait获取子进程退出码(方法一是父进程先结束后子进程被Init(现在随着内核的发展不一定是1)收养,Init之后调用wait获取子进程退出码;方法二是父进程直接调用wait,)但是两种方法又有区别,就是父进程调用wait会阻塞,等子进程执行完之后,父进程才会执行.
若想父进程调用wait不阻塞,那么我们需要结合信号一起.具体在信号那一节用代码演示;