一、孤儿进程
- 父进程在子进程结束之前终止,那么子进程就变为孤儿进程
孤儿进程的处理
- 对于其父进程已经终止的所有孤儿进程,它们的父进程都改变为init进程。我们称这些进程由init进程领养
- 其操作过程大致是:在一个进程终止时,内核逐个检查所有活动进程,以判断它是否是正要终止的进程的子进程,如果是,则该进程的父进程ID就更改为1( init进程的ID)。这种处理方法保证了每个进程有一个父进程
- 一个由init进程领养的孤儿进程终止时会发生什么?它会不会变成一个僵死进程?
- 答案是“否”。因为init被编写成只要有一个子进程终止,init就会调用一个wait()函数取得其终止状态。因此僵死进程就会被init清除。这样也就防止了在系统中有很多僵死进程
- 当提及“一个init的子进程”时,这指的是init直接产生的进程,或者是其父进程已终止,由init领养的进程
二、僵死进程
- 一个已经终止、但是其父进程尚未对其进行善后处理(获取终止子进程的有关信息、释放它仍占用的资源)的进程被称为僵尸进程
- 设置僵死状态的目的:父进程一般需要跟踪子进程的退出状态,因此,当子进程结束运行时,内核不会立即释放该进程的进程表表项(信息包括该进程的ID,终止状态、以及资源利用率等),以满足父进程后续对该子进程退出信息的查询(如果父进程还在运行的话)
- 一个进程处于僵死状态之后,如果父进程调用wait、waitpid函数来处理子进程,那么僵死状态就会消失
如果僵死进程的父进程提前退出了怎么办?
- 我们知道僵死进程会一直等待父进程来处理自己,如果僵死在等待的过程中父进程退出了(也就是说父进程没有对子进程进行处理就退出了),那么僵死进程也会被交给init进程处理(僵死进程类似于变为了孤儿进程)
- 当僵死进程传递给init管理之后,init就会调用wait()函数对齐进程处理,从而处理掉僵死进程
- wait、waitpid函数见文章:https://blog.csdn.net/qq_41453285/article/details/88992605
三、孤儿进程与僵死进程的区别
- 僵死进程是子进程已经结束,父进程依然存在,但是父进程还没有对子进程进行处理
- 孤儿进程是父进程在子进程结束之前终止
四、僵死进程的处理(SIGCLD、SIGHCLD信号处理)
- 虽然我们可以在父进程中调用wait、waitpid来等待子进程的结束,但是wait、waitpid的调用可能会影响父进程原本想要进行的工作,因此为了提高程序的效率,我们可以借助SIGCLD/SIGCHLD信号来处理子进程:在父进程中捕获SIGCLD/SIGHCLD信号,并在信号处理函数中调用wait/waitpid函数来“彻底结束”一个子进程
- 子进程状态改变(终止或停止)后产生此信号(SIGCLD/SIGHCLD),传递给父进程
- SIGCLD、SIGHCLD信号处理的详细介绍:
下面是SIGCLD信号处理的伪代码
void static void handle_child(int sig); int main() { /*...*/ signal(SIGCLD,handle_child); //为SIGCLD信号绑定信号处理函数 /*...*/ } void static void handle_child(int sig) { pid_t pid; int stat; while((pid=waitpid(-1,&stat,WNOHANG))>0) { /*对结束的子进程进行善后处理*/ } }