个人主页:Lei宝啊?
愿所有美好如期而遇
目录
首先,子进程退出,如果父进程不去回收子进程资源,读取子进程的PCB,那么就会使子进程变成僵尸进程,进而导致内存泄漏,
另外,僵尸进程无法通过控制信号杀死,也就是说kill -9无法杀掉僵尸进程,因为僵尸进程本来就已经死了,只剩下PCB,在等待被读取。
进程通过等待的方式,回收子进程资源,读取进程PCB来获取子进程退出信息。(一般来说,如果父进程不做等待,那么父进程可能会比子进程先结束,那么子进程就会成为孤儿进程,这当然不是我们想看到的,看示例)。
我们可以看到父进程先退出,然后子进程成为孤儿进程,被操作系统所接管,几秒后子进程的资源被回收。
接下来在这里我们来解释waitpid的参数
参数pid : -1? 等待任意一个子进程,与wait等效。
? ? ? ? ? ? ? ? ?>0 等待指定pid子进程。
参数status:32位,我们只看后16位,格式为8位退出码+7位信号编号,还有一位core dump标志
参数options:阻塞等待(参数为0)和非阻塞等待(参数为WNOHANG)
status我们用来获取进程的退出信息,我们先解释wait函数,看代码示例:
?我们也就看到wait成功回收了子进程。
wait(&status)等同于waitpid(-1,&status,0),属于阻塞等待,也就是说,父进程会等待子进程结束再继续执行。
我们将下面的waitpid(-1,&status,0)替换为wait(&status),得到的现象是相同的。
在fork之后,父进程应该执行他的输出语句,应该和子进程是同步的,但是现象就是子进程先执行完,父进程等待子进程结束再继续执行。?
status为什么是256呢?首先我们的进程是正常结束的,也就是没有异常信号,所以status后7位为0,而我们给子进程设置的退出码为1,则他的补码是这样的0000 0001,status?补码就是0000 0000 0000 0000 0000 0001?0000 0000,所以结果就是256。
接下来我们使用非阻塞等待:
我们这里使用基于非阻塞的轮询访问,也就是循环去调waitpid函数,同时也可以对比得出wait会阻塞在该行直到子进程结束,而waitpid不会阻塞,子进程未结束返回给rid为0,继续向下执行,如果rid>0,也就是子进程结束,返回的值为子进程的pid,rid<0,则异常,我们直接退出。