父进程与子进程的生命周期一般是不相同的,父子进程互有长短,这就引出了两个问题:孤儿进程与僵尸进程的产生。
孤儿进程
首先看一段示例代码:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(int argc, const char *argv[]) { pid_t pid; pid = fork(); if (pid < 0) { perror("fork error"); return -1; } else if (pid == 0) { /* child */ printf("The child process, id = %d parent id = %d\n", getpid(), getppid()); while(1); } else { /* parent */ printf("The parent process, id = %d\n", getpid()); } return 0; }点击复制复制失败已复制
编译并执行,结果如下所示:
$ gcc main.c && ./a.out The parent process, id = 60297 The child process, id = 60298 parent id = 60297点击复制复制失败已复制
提示
接下来的部分和原版产生了偏差,主要差别在于父进程ID哪里,详见:原版
代码分析:上述案例代码,主进程运行完成之后就退出了,而子进程被 while(1)
死循环阻塞了。接下来查看进程信息:
$ ps axj | grep a.out PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 1113 60298 60297 56354 pts/0 60972 R 1000 2:30 ./a.out $ ps axj | grep 60297 PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 1113 60298 60297 56354 pts/0 61250 R 1000 3:30 ./a.out点击复制复制失败已复制
可以发现, 60279
这个父进程找不到,相应的父进程却变成了 1113
。子进程处于运行态( R
),此子进程就是一个孤儿进程。
接下来看看 1113
这个进程是什么东西
$ ps axj | grep 1113 PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 1 1113 1113 1113 ? -1 Ss 1000 0:00 /lib/systemd/systemd --user点击复制复制失败已复制
可以看出这时 systemd
进程。在这这里需要说明一点的是,进程在退出时,通常由该进程的父进程对其资源进行回收及释放资源。如果该进程的父进程提前退出,那么此时该进程将失去了“父亲”,则成为了“孤儿”。
僵尸进程
僵尸进程其实是进程的一种状态,即僵尸态。在进程的状态笔记中介绍了僵尸进程的形成。进程的僵尸态和死亡态很接近。唯一不同的是,死亡进程,即进程退出,释放所有资源;而僵尸进程,即进程退出但没有释放资源。因此在实际的编程过程中,应尽量关注这一点,避免产生僵尸态的进程,因为僵尸进程不执行任何任务,却占有系统资源。如果僵尸进程太多,就会导致系统浪费,示例如下:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(int argc, const char *argv[]) { pid_t pid; pid = fork(); if (pid < 0) { perror("fork error"); return -1; } else if (pid == 0) { /* child */ printf("The child process, id = %d parent id = %d\n", getpid(), getppid()); } else { /* parent */ printf("The parent process, id = %d\n", getpid()); while(1); } return 0; }点击复制复制失败已复制
编译并执行:
$ gcc main.c && ./a.out The parent process, id = 65560 The child process, id = 65561 parent id = 65560 点击复制复制失败已复制
注意
终端可没有退出哦!
接下来查看进程信息:
$ ps axj | grep a.out PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 56354 65560 65560 56354 pts/0 65560 R+ 1000 0:51 ./a.out 65560 65561 65560 56354 pts/0 65560 Z+ 1000 0:00 [a.out] <defunct>点击复制复制失败已复制
可以看出,如果父进程不退出子进程退出,此时父进程不会主动回收子进程的资源,子进程成为僵尸进程(状态为: Z+
, Z
表示僵尸态)。僵尸进程的产生,往往是因为父进程没有对子进程的资源进行回收处理。因此为了避免这样的结果出现,程序需要在子进程选择退出时,由父进程进行资源的回收处理。