僵尸进程
父进程调用fork()创建子进程,通常情况下,子进程运行时,父进程调用wait()或waitpid()函数等待子进程,子进程退出后,父进程接收到子进程的退出码,并释放子进程资源。
但如果父进程没有接收到子进程的退出码,那子进程的资源便无法回收,子进程将会以终止状态保持在进程表中,直到父进程读取它的退出码,这种子进程也就叫僵尸进程。
僵尸进程的危害
1.僵尸进程虽然已经不再工作,但它自己那部分资源却未得到释放,会造成内存泄漏
2.计算机能够运行的进程是有限的,僵尸进程过多将导致新进程无法创建
3.僵尸进程一直保持退出状态,这是需要task_struct维护的,有一定开销。
模拟实现僵尸进程
//模拟一个持续30s的僵尸进程
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<stdlib.h>
4
5
6 int main()
7 {
8 pid_t pid = fork();//创建一个子进程
9
10 if (pid<0)//创建子进程失败
11 {
12 printf("create child process is failed!!\n");
13 }
14
15 else if (pid >0)//父进程
16 {
17 printf("parent process is sleeping:%d\n",getpid());
18 sleep(30);
19 }
20 else//子进程
21 {
22 printf("this is child process");
23 sleep(5);
24 exit(EXIT_SUCCESS);
25 }
26 return 0;
27
28 }
运行上面的代码,我们用ps -aux查看一下进程的状态:
我们发现,这个pid为3415的进程就是我们所要的僵尸进程zombie。
再用kill -9试着强制终止该进程:
连kill -9这样的强制命令都无法终止僵尸进程,可见僵尸进程在计算机内是多么顽固的存在。
正确处理僵尸进程的方法是调用wait()或者waitpid()函数,让父进程及时接收到子进程返回的SIGCHID信号并释放资源。
孤儿进程
当父进程先于子进程退出,子进程就成为孤儿进程,子进程会被孤儿院init进程领养(意为init进程作为子进程的新父进程),由init进程为他回收资源。
代码实现
1 #include<stdio.h>
2 #include<stdlib.h>
3
4
5 int main()
6 {
7 pid_t pid = fork(); //创建子进程
8 if (pid < 0)//创建失败
9 {
10 printf("fork error!!\n");
11 return -1;
12 }
13 else if (pid >0)//父进程
14 {
15 printf("father is gone!!\n");
16 exit(EXIT_SUCCESS);
17 }
18 else//子进程
19 {
20 printf("my father is gone!! %d\n",getpid());
21 sleep(20);
22 }
23 return 0;
24 }
上述代码运行后,结果如下:
我们再来看一下子进程的状态:
由图可知,子进程已经被1号进程(init进程)领养,1号进程来为该进程释放资源。