2021.4.6 字节实习一面,面试官在考察我操作系统知识时,在我回答“父进程调用 wait 可以防止子进程僵尸进程出现” 后,追问我 “那操作系统为什么要这么设计,而不是在子进程退出之后就直接将其视为退出,而不是僵尸进程”。当时没答出来,面试结束后我查阅了相关的资料,对 wait 有了进一步的了解。
曾经在学习《Unix系统编程》的时候接触到 wait 和 waitpid 的概念,并且还做了笔记,只不过当时对这两个系统调用的理解还不是很深。
wait 的作用是给父进程监听子进程状态的改变的:
- 进程被 terminate
- 进程被 suspend
- 进程从 suspend 中恢复
对于 terminate 的情况,执行 wait 可以让系统释放子进程的相关资源,否则子进程就会变成僵尸状态。当一个进程成为僵尸状态时,内核会存储该进程的一些信息,如 PID、终止状态、资源使用信息。这是为了等待父进程晚些时候执行 wait 来获取子进程的状态。如果这个父进程提前退出,则 init 进程会负责起执行 wait 的责任。
也就是说,一个进程可能会经历僵尸状态,时间长短取决于父进程调用 wait 是否及时。当父进程退出之后,一个僵尸进程会变成孤儿进程,由 init 来执行 wait。由于僵尸进程已经退出,所以无法 kill 掉。
总之一句话,wait & waitpid 可以让父进程获取子进程的状态变化,在获知子进程退出状态后,系统内核会回收子进程的相关资源。
下面是一个测试,子进程退出后,父进程未调用 wait 回收
1 |
|
可以看到,[a.out] 为 Z 状态
1 | 4938 14758 14758 14758 pts/0 28627 Ss 0 0:00 | | \_ /bin/bash |