1. 孤儿进程
如果父进程先退出,子进程还没退出那么子进程将被托孤给init进程,这是子进程的父进程就是init进程(1号进程).
用到的Linux函数有:fork 创建一个新进程,vfork 创建一个子进程,以供执行新程序,常与execve等同时使用,execve 运行可执行文件,getpid 获取进程标识号,getppid 获取父进程标识号,wait 等待子进程终止,waitpid 等待指定子进程终止,exit 中止进程,pause 挂起进程,等待信号
具体测试代码的可以看博客https://www.cnblogs.com/wannable/p/6021617.html
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <signal.h>
int main(void)
{
pid_t pid ;
signal(SIGCHLD,SIG_IGN);
printf("before fork pid:%d
",getpid());
int abc = 10;
pid = fork();
if(pid == -1)
{
perror("tile");
return -1;
}
if(pid > 0) //父进程先退出
{
abc++;
printf("parent:pid:%d
",getpid());
printf("abc:%d
",abc);
sleep(5);
}
else if(pid == 0){ //值进程后退出,被托付给init进程
abc++;
printf("child:%d,parent: %d
",getpid(),getppid());
printf("abc:%d",abc);
sleep(100);
}
printf("fork after...
");
}
测试结果:我们执行程序后由于子进程进入sleep(100),而父进程先退出.通过ps -ef命令我们可以知道,此时27710号进程的父进程编程了1号进程.也就是我们所说的init进程.
before fork pid:27709
parent:pid:27709
abc:11
child:27710,parent: 27709
fork after...
disda 27710 1 0 10:47 pts/1 00:00:00 ./review
disda 27713 25948 47 10:47 pts/3 00:00:00 ps -ef
2. 僵尸进程
一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。.僵尸进程还会消耗一定的系统资源,并且还保留一些概要信息供父进程查询子进程的状态可以提供父进程想要的信息.一旦父进程得到想要的信息,僵尸进程就会结束.
int main(void)
{
pid_t pid ;
//signal(SIGCHLD,SIG_IGN);
printf("before fork pid:%d
",getpid());
int abc = 10;
pid = fork();
if(pid == -1)
{
perror("tile");
return -1;
}
if(pid > 0)
{
abc++;
printf("parent:pid:%d
",getpid());
printf("abc:%d
",abc);
sleep(20);
}
else if(pid == 0){
abc++;
printf("child:%d,parent: %d
",getpid(),getppid());
printf("abc:%d",abc);
exit(0);
}
printf("fork after...
");
同样通过ps -ef我们可以得知进程信息和进程pid,可以看到子进程就是处于defunct状态.
disda 27881 23047 0 11:12 pts/1 00:00:00 ./fork01
disda 27882 27881 0 11:12 pts/1 00:00:00 [fork01] <defunct>
僵尸进程危害:如果进程不调用wait / waitpid的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免
避免僵尸进程:通过信号机制,子进程退出时向父进程发送SIGCHILD信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait进行处理僵尸进程。
或者fork两次,原理是将子进程成为孤儿进程,从而其的父进程变为init进程,通过init进程可以处理僵尸进程。