🚀 优质资源分享 🚀
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
💛Python量化交易实战💛 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
进程最后的遗言
前言
在本篇文章当中主要给大家介绍父子进程之间的关系,以及他们之间的交互以及可能造成的状态,帮助大家深入理解父子进程之间的关系,以及他们之间的交互。
僵尸进程和孤儿进程
僵尸进程
在 Unix 操作系统和类 Unix 操作系统当中,当子进程退出的时候,父进程可以从子进程当中获取子进程的退出信息,因此在 类 Unix 操作系统当中只有父进程通过 wait 系统调用读取子进程的退出状态信息之后,子进程才会完全退出。那么子进程在程序执行完成之后(调用 _exit 系统调用之后),到父进程执行 wait 系统调用获取子进程退出状态信息之前,这一段时间的进程的状态是僵尸进程的状态。
正式定义:在 Unix 或者类 Unix 操作系统当中,僵尸进程就是哪些已经完成程序的执行(完成_exit 系统调用退出了程序),但是在内核当中还有属于这个进程的进程表项。这个表项的作用主要是让父进程读取子进程的退出状态信息 (exit status)。
在后文当中我们有一个例子详细分析这个退出状态的相关信息。一旦父进程通过 wait 系统调用读取完子进程的 exit statis 信息之后,僵尸进程的进程表项就会从进程表(process table)当中被移除,这个进程就算是彻底消亡了(reaped)。
如果系统当中有很多处于僵尸状态的进程而父进程又没有使用 wait 系统调用去得到子进程的退出状态,那么系统当中就会有很多内存没有被释放,这就会导致资源泄露。
下面是一个僵尸进程的例子,对应的代码名称为 Z.c:
| | #include |
| | #include |
| | |
| | |
| | int main() { |
| | printf("parent pid = %d\n", getpid()); |
| | if(fork()) { |
| | while(1); |
| | } |
| | printf("child process pid = %d\n", getpid()); |
| | return 0; |
| | } |
上面C语言对应的python代码如下:
| | import os |
| | |
| | if \_\_name\_\_ == "\_\_main\_\_": |
| | print(f"parent pid = {os.getpid()}") |
| | pid = os.fork() |
| | if pid != 0: |
| | # parent process will never exit |
| | while True: |
| | pass |
| | # child process will exit |
| | print(f"child process pid = {os.getpid()}") |
现在执行上面的程序,得到的结果如下所示:
从上图当中我们可以看到父进程一直在进行死循环的操作,而子进程退出了程序,而现在应该处于僵尸进程状态。而我们通过 ps 命令得到的进程状态的结果,根据进程号得到子进程的状态为 Z+
,这个状态就表示这个进程就是一个僵尸进程。我们在这里再简要谈一下命令 ps 对进程的状态的各种表示: