写在前面:小生纯业余选手,开此博仅仅是为了积累,纯当笔记来用。如有看官光临小生博客,请不要相信我的代码就是正确的。如果您发现了错误也恳请耽误您一点时间,请您在下面指出来,不胜感激!
如果发现一些笔记的说法完全是错误的请建议我删除!
通过fork可以创建新的进程,通过fork创建的新进程称作子进程,原进程称作父进程。父进程与子进程是两个独立的进程,他们不会因“父子”关系来放弃使用CPU或内存资源。他们各自在proc下创建各自的文件。
问题:
如果进程A创建了进程a
1.进程A在执行过程中退出了而进程a还在继续执行,进程a会怎样?
回答:进程a将成为孤儿进程统一挂在Linux的根进程下。
2.进程A在执行的过程中进程a退出了,进程a会怎样?
回答:进程a将成为僵死进程,占用了进程任务管理树的一个节点,如果僵死进程过多会产生问题,所以要回收僵死进程。
3.问题如何回收僵死进程,如何知道a进程处于僵死状态?
可以通过pstree命令来观察Linux进程树,ps命令来观察进程
僵死进程会在进程树中占用一个节点,通过ps命令可以看到僵死进程的STAT是Z……<defunct>
下图是Linux进程树
注意上图左侧黑色大括号的部分
运行如下代码观察进程树中大括号部分的内容
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/wait.h> #include<signal.h> int main() { if(fork() == 0) { printf("child\n"); sleep(200); printf("child quit\n"); while(1); } else { sleep(20); printf("parent quit!\n"); while(1); } return 0; }进程树中的黑色大括号部分如下
如下代码产生一个孤儿进程,通过pstree命令可以看到孤儿进程将被挂在根进程(init进程)下。
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/wait.h> #include<signal.h> int main() { if(fork() == 0) { sleep(40); printf("child quit\n"); } else { sleep(20); printf("parent quit!\n"); } return 0; }
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/wait.h> #include<signal.h> int main() { if(fork() == 0) { sleep(20); printf("child quit\n"); } else { sleep(40); printf("parent quit!\n"); } return 0; }
<span style="font-size:18px;">#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/wait.h> #include<signal.h> int main() { if(fork() == 0) { sleep(20); printf("child quit\n"); } else { int status; wait(&status); printf("colecting defunct\n",WEXITSTATUS(status)); sleep(40); } return 0; }</span>
对于上一个例子只需要等待子进程结束就能通过wait回收,但是子进程会在什么时候结束呢?这就需要通过Linux信号的机制来实现,下面代码简单说明信号的应用。
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/wait.h> #include<signal.h> void deal(int s) { int status; wait(&status); printf("collecting............\n"); sleep(10); printf("collecting over:%d\n",WEXITSTATUS(status)); } int main() { if(fork() == 0) { sleep(20); printf("child quit\n"); } else { signal(SIGCHLD,deal); while(1) { sleep(1); printf("parent\n"); } } return 0; }
上面代码段中signal函数在哪个进程中被调用,使用权就属于哪一个进程。signal函数要在调用结束之后才返回到调用signal的进程中继续进程的执行(通过deal函数中的sleep函数可以清楚地看到这一点)!