僵尸进程
在父进程中fork一个子进程,当子进程执行完成执行exit(0)后,将子进程的退出码存储在与之对应的PCB中。父进程则通过wait来获取退出码,并根据退出码来了解子进程的信息。
僵尸进程的概念:当子进程先于父进程结束时,父进程没有获取到子进程的退出码
孤儿进程的概念:父进程先于子进程结束,此时将由一个个叫INIT(pid=1,第一个被fork出来的进程) 的进程来“收养”这个孤儿进程。
我们将通过一段代码来了解僵尸进程:
让子进程运行打印三次先于父进程结束,每fork一次 我们都活会打印出进程的和它的父进程的pid
在运行程序时,将其放在后台运行(只需在后面加上&即可),可以看到,首先打印的是父亲进程,它的pid为3522,父亲进程的父进程是3483。在登陆Linux后,会获得一个叫做bash的进程,bash进程繁衍出其他所有进程。我们前面讲到的INT进程就是bash复制出来的第一个进程。所以父进程会有系统来做处理,我们关注的只是父进程复制出来的子进程。
我们在执行ps命令时会发现有两个text进程,那其实就是我们的父子进程。再看pid分别为3526,3527。我们可以分析出pid3527所对应的进程就是我们的子进程。而正如我们分析的那样就是系统为我们标明的僵尸进程。
那什么是孤儿进程呢,当我们将父子进程运行的次数换一下后,我们看一下会发生什么:
此时当父进程运行完后,我们发现剩余的子进程它的父进程的pid都变成了1。这就是我们所说的孤儿进程,它被我们的INIT进程所收养。
解决的方法
我们需要一个wait方法来接受返回值,它的头文件:#include <unistd.h>
在父进程中定义一个wait用来接受子进程的返回码,为了便于观察我们将返回码设为2.
s="father";
n=8;
int val=0;
pit_t pid=wait(&val);
printf("val=%d,pid=%d\n",val,pid);
此时在第四行中父进程接收到的pid为3631,这个pid正好是子进程的pid。此时val的值是512,但是我们的返回值设置的是2。这是因为我们将返回值左移了八位,那它在二进制中是这样的:
0010 0000 0000。我们只需要将二进制>>8位即可。