Linux5.2、进程等待

个人主页:Lei宝啊 

愿所有美好如期而遇


目录

进程等待的必要性

进程等待的方法

获取子进程status


进程等待的必要性

首先,子进程退出,如果父进程不去回收子进程资源,读取子进程的PCB,那么就会使子进程变成僵尸进程,进而导致内存泄漏,

另外,僵尸进程无法通过控制信号杀死,也就是说kill -9无法杀掉僵尸进程,因为僵尸进程本来就已经死了,只剩下PCB,在等待被读取。

进程通过等待的方式,回收子进程资源,读取进程PCB来获取子进程退出信息。(一般来说,如果父进程不做等待,那么父进程可能会比子进程先结束,那么子进程就会成为孤儿进程,这当然不是我们想看到的,看示例)。

Linux5.2、进程等待_第1张图片

我们可以看到父进程先退出,然后子进程成为孤儿进程,被操作系统所接管,几秒后子进程的资源被回收。

Linux5.2、进程等待_第2张图片

进程等待的方法

Linux5.2、进程等待_第3张图片

获取子进程status

接下来在这里我们来解释waitpid的参数

参数pid : -1  等待任意一个子进程,与wait等效。

                 >0 等待指定pid子进程。

参数status:32位,我们只看后16位,格式为8位退出码+7位信号编号,还有一位core dump标志

参数options:阻塞等待(参数为0)和非阻塞等待(参数为WNOHANG)

status我们用来获取进程的退出信息,我们先解释wait函数,看代码示例:

Linux5.2、进程等待_第4张图片

Linux5.2、进程等待_第5张图片

Linux5.2、进程等待_第6张图片Linux5.2、进程等待_第7张图片

Linux5.2、进程等待_第8张图片 我们也就看到wait成功回收了子进程。

wait(&status)等同于waitpid(-1,&status,0),属于阻塞等待,也就是说,父进程会等待子进程结束再继续执行。

我们将下面的waitpid(-1,&status,0)替换为wait(&status),得到的现象是相同的。

Linux5.2、进程等待_第9张图片

在fork之后,父进程应该执行他的输出语句,应该和子进程是同步的,但是现象就是子进程先执行完,父进程等待子进程结束再继续执行。 

Linux5.2、进程等待_第10张图片

status为什么是256呢?首先我们的进程是正常结束的,也就是没有异常信号,所以status后7位为0,而我们给子进程设置的退出码为1,则他的补码是这样的0000 0001,status 补码就是0000 0000 0000 0000 0000 0001 0000 0000,所以结果就是256。

接下来我们使用非阻塞等待:

Linux5.2、进程等待_第11张图片

我们这里使用基于非阻塞的轮询访问,也就是循环去调waitpid函数,同时也可以对比得出wait会阻塞在该行直到子进程结束,而waitpid不会阻塞,子进程未结束返回给rid为0,继续向下执行,如果rid>0,也就是子进程结束,返回的值为子进程的pid,rid<0,则异常,我们直接退出。

Linux5.2、进程等待_第12张图片

补充 

  • wait和waitpid是系统调用,这个我们是清楚的,而且他们是为了获取退出的子进程的退出码和信号,我们就有疑问,难道父进程不可以直接获取,或者说我们直接定义一个变量。我们自己获取吗?是的,不可以,首先进程之间是相互独立的,父进程无法直接去读取子进程的数据,因为进程是操作系统所管理的,他的数据不允许用户直接读取,只能通过系统调用,也就是我们的wait和waitpid获取,然后通过我们上面提到的方式组合在status里,返回给父进程。
  • 同时,我们可以从status中通过位运算提取出信号和退出码:                                                    提取信号:status & 0x7F  也就相当于&0000 0000 0000 0000 0000 0000 0111 1111              提取退出码:stauts >> 8 & 0xFF, 也就相当于& 0000 0000 0000 0000 0000 0000 1111 1111
  • waitpid,我们基于非阻塞轮询访问时,父进程可以进行其他操作,执行其他函数。

你可能感兴趣的:(Linux,Linux)