当前位置:网站首页 > 技术博客 > 正文

linux中waitpid的作用




  1. 父进程等待子进程退出,是因为父进程需要子进程退出的信息,和完成功能的状态如何;
  2. 可以保证时序问题:子进程先退出,父进程再退出;
  3. 可以预防子进程成为僵尸进程,防止内存泄漏的问题;而这我们需要父进程wait等待子进程退出之后,释放它的僵尸资源,也就子进程的PCB;
  4. 并且我们需要知道,一旦进程成为僵尸状态,即使你使用 也杀不死这个僵尸进程滴,只能通过父进程等待wait回收它;

wait函数的作用是父进程调用,等待子进程退出,回收子进程的资源;

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:
成功返回被等待进程pid,失败返回-1。
参数:
输出型参数,获取子进程退出状态,不关心则可以设置成为NULL


在这里插入图片描述


该测试代码:测试wait函数返回值,测试wait回收僵尸进程;

 

监视 进程的脚本程序;

 

在这里插入图片描述


pid_ t waitpid(pid_t pid, int *status, int options);
返回值:
当正常返回的时候waitpid返回收集到的子进程的进程ID;
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
pid:
Pid=-1,等待任一个子进程。与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。
status:
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
options:
参数为0:也就是阻塞版本的等待,也就是说该waitpid在子进程没有退出情况下就不会返回,就和wait的使用一模一样,因为wait的使用就是阻塞版本的等待方式;
参数为WNOHANG: 这是一个宏,表示调用wait为非阻塞的版本,非阻塞也就以为执行带waitpid函数会立即返回
而设置这个参数:返回情况有以下几种:

  1. 若pid指定的子进程没有结束,则waitpid()函数返回0,父进程不予以等待;
  2. 若正常结束,则返回该子进程的ID;
  3. 若等待失败,即返回小于0;

第一层理解
对于 waitpid 函数就是 wait函数的增强版;
waitpid 函数 的使用方式 waitpid(-1,NULL,0) 等价 wait 函数的使用 wait(NULL) 两者这样使用一样的;


第二层理解

  1. 对于status参数,其实是一个输出型参数,也就是父进程调用该waitpid时候,可以传入一个 地址给 status;待该waitpid执行结束返回时候,会得到该staus的值;
  2. status的值表示子进程的退出码的信息,也就是父进程为了得到子进程的退出信息,就是可以通过设置一个参数传入给status,获得子进程的信息;
  3. status的退出信息:也就是子进程退出的信息,而进程退出只有三种状态:正常退出执行代码结果正确,异常退出,正常退出了但是执行的结果不正确;异常退出的进程:本质是因为收到了某种信号,才会异常退出,而对于正常退出的进程,才有退出码而言说法;不管是信号还是退出码,都是子进程需要返回给父进程中stauts参数的;
  4. 其次这个 stauts,父进程获得子进程的status;不可以简简单单的认为 stauts就是一个整形int,我们要把它为一个
    位图;对于32位的int类型来说:
    我们status是在每一个位上设置它的信息来使用的;高16位不使用,而低16位使用来表示具体信息;

3.2.1获得子进程的status信息

在这里插入图片描述


也就是说:对于子进程退出的状态信息:在8-16位的表示退出码的信息,低7位表示终止信号信息;而第8位单独一个表示core dump 状态,我们暂时不关系这个信息;


那么我们是如何获得该子进程的退出的信息的呢?

我们可以通过
(stauts >> 8 )& 0xFF;获得子进程的退出码;
stauts & 0x7F; 获得子进程的终止信号;


代码验证一下:

 


这里我并没演示退出时候异常退出的情况,也就是我没有演示发送信号给子进程会有什么样的状态:
其实就是在另一个窗口给子该进程发送一个信号值,当进程退出时候,这个信号就会被返回到父进程的stauts中,这样就能获取了;
当然异常的情况还有内存越界,什么段错误,什么除0操作,一旦程序出现这些状态,也可以在父进程waitpid中的参数status中获取得到,我就不演示了;感兴趣可以试一试;


我们获得子进程的退出码,其实可以不用通过:位操作的获取,
在我们的C程序中提供一个宏:
: 若为正常终止子进程返回的状态,则为真;
那么我们就可以通过if判断该条件是否真假,获得子进程的退出码:
获得的方式为这个宏: 若WIFEXITED非零,提取子进程退出码。


测试子进程正常退出,获取它的状态码:

 

测试代码的结果:
在这里插入图片描述


假如子进程异常退出,那么就会执行else分支语句,不会获得退出码;


3.2.2 理解下waitpid内部是如何返回status的

我们知道:当我们创建进程时候,在内核是有该进程的PCB的,而PCB里面存放着我们进程退出的信息;
也就是有退出码和终止信号,在用户层父进程调用waitpid函数时候,该函数进入内核会给把我们的子进程的PCB退出码和终止信号信息给status赋值;
也就是大概类似这样的操作:
在这里插入图片描述


3.2.3 waitpid 的options参数的理解

该参数设置:一般设置为WNOHANG:表示为父进程是以非阻塞的方式等待子进程;

但是非阻塞方式等待子进程退出就有几种情况:
> 1.子进程没有退出,但是父进程调用的waitpid返回了0,这也表示等待子进程成功,只不过子进程没有退出,此时表示需要继续做父进程的事情;
2. 子进程退出了,f父进程调用waitpid函数返回子进程的PID, 也就是等待成功了,这时候我们在父进程可以拿到子进程的退出状态信息;
3. waitpid等待子进程退出失败,waitpid就会返回小于0的值,此时就可以做一些输出错误信息给用户;

阻塞本质就是:调用该函数的父进程由在运行队列被放入到了等待队列中等待,同时修改进程状态为S;
waitpid返回的本质也就是:将该父进程从等待队列拿到运行队列中执行;


测试options:WNODHANG
非阻塞等待子进程;
一般而言我们会使用一种叫做非阻塞轮回检测技术来检测子进程的退出状态,也就是说:我希望子进程退出能够被我父进程检测到,同时我又不希望我父进程处于阻塞等待,也就是父进程不希望自己什么事都不可以做,只等子进程退出返回;


如何做到呢?

 

在这里插入图片描述


版权声明


相关文章:

  • 分布式缓存服务redis2025-04-30 17:30:07
  • 自动开关机软件哪个好2025-04-30 17:30:07
  • 指针运算c语言2025-04-30 17:30:07
  • 安卓textview字体加粗2025-04-30 17:30:07
  • tftpd linux2025-04-30 17:30:07
  • 数据结构第5章树和二叉树答案2025-04-30 17:30:07
  • linux性能指标监控工具2025-04-30 17:30:07
  • java测试项目2025-04-30 17:30:07
  • 结构体数组的常见问题2025-04-30 17:30:07
  • 深度置信网络 简单理解2025-04-30 17:30:07