进程等待

之前说,子进程退出,父进程如果不管不顾,就可能造成“僵尸进程”的问题,进而造成内存泄露,进而,进程一旦变成僵尸状态,杀人不眨眼的”kill -9”也无能为力,因为谁也没有办法杀死一个已经死去的进程,最后,父进程派给子进程的任务完成的如何,我们需要知道,如子进程运行完成,结果是还是不对,或者是否正常退出,我们需要知道

父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

进程等待方法

wait()


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

waitpid()

头文件: #include<sys/type.h>#include<sys/wait.h>
返回值:(1)当正常返回的时候waitpid返回收集到的子进程的进程ID(2)如果设置了选项WNOHANG,而调用中waitpid发现已经没有已经可以退出的子进程可收集,则返回0(3)如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在

原型

pid_t waitpid(pid_t pid,int *status,int options)

参数说明:

1.pidpid=-1,等待任一个子进程,与wait等效pid>0,等待其进程ID与pid相等的子进程
2.statusWIFEXITED(status):    若为正常终止子进程返回的状态,则为真(此参数是查看进程是否是正常退出)WEXITSTATUS(status):  若WEXITSTATUS非零,提取子进程退出码(查看进程的退出码)
3.optionsWNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待,若正常结束,则返回该子进程的ID

(1)如果子进程已经退出,调用wait/waitpid会立即返回,并且释放资源,获得子进程退出信息
(2)如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞
(3)如果不存在该子进程,则立即出错返回
(4)子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止)

获取子进程status

wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充
如果传递NULL,表示不关心子进程的退出状态信息,
否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程

status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(只研究status低16比特位)

正常终止

status & 0x7f,   如果是0的话,那就表示正常退出
0xff是0111111,status 按位与0x7f,表示取出status的低7位

当正常终止的时候,status高8位就是子进程的退出码

status & 0xff,就是取出status的高8位

异常终止

status & 0x7f,   不为0的话,那就表示异常退出

判断子进程正常/异常退出的时候:
status & 0x7f(status按位与0x7f)的时候,按位与7位就好,如果按位与的结果是0,那就表示子进程正常退出,按位与的结果不是0,那就表明子进程异常退出

阻塞式等待&非阻塞式等待


1.阻塞式等待子进程先执行,而且父进程会等待子进程执行结束,再去执行自己
2.非阻塞式等待子进程和父进程谁先执行不确定,父进程如果先执行的话,父进程会一边等待子进程而另一边又做自己的事情,即就是等待子进程和执行自己的事情是同步进行的

示例

进程的阻塞等待方式

wait()

代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/wait.h>
int main()
{pid_t pid;if((pid=fork())==-1){perror("fork()");exit(1);}if(pid==0)//child{sleep(30);exit(10);}if(pid>0){int status;int ret=wait(&status);if(ret>0&&((status&0x7f)==0)){printf("child exit code:%d\n",(status>>8)&0xff);}//status>>8表示把status的低8位右移出去//(status>>8)&0xff表示把status的低8位右移出去(系统会给status会补够32位),然后与0xff按位与,得到status的低8位,此结果就是子进程的退出码else if(ret>0){//异常退出printf("sig code: %d\n",status&0x7f);}}return 0;
}

运行结果

等待30s之后

此运行结果是子进程正常退出的场景

在另一个终端把子进程kill掉

ps:   ps -ef | grep a.out  是查看进程的pidkill -9+pid 是杀死进程ID为pid的进程
例图中 kill -9 2612 就是杀死进程为2612的进程


进程退出信号是:9号信号

waitpid()

代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>//waitpid()的头文件
int main()
{pid_t pid=fork();if(pid<0){perror("fork");exit(1);}if(pid==0){printf("child is run,child pid is :%d\n",getpid());//getpid()得到的是当前进程的pidsleep(5);exit(10);}if(pid>0){int status=0;pid_t ret=waitpid(-1,&status,0);//阻塞式等待,等待5秒printf("this is for test wait.\n");if(WIFEXITED(status)&&(ret==pid)){printf("child is 5s succes.child exit code is :%d\n",WEXITSTATUS(status));}else if(ret>0){printf("wait child failed.\n");exit(1);}}return 0;
}

运行结果:

等待5秒过后

阻塞式等待,父进程等待子进程执行,然后在执行自己

进程的非阻塞等待方式

waitpid()

代码:

include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{pid_t pid=fork();if(pid<0){perror("fork");exit(1);}if(pid==0){printf("child is run,child pid is :%d\n",getpid());sleep(5);printf("child is run.\n");exit(10);}if(pid>0){int status=0;pid_t ret=0;//记得需要声明retdo{ret=waitpid(-1,&status,WNOHANG);//非阻塞式等待if(ret==0){printf("child is running,\n");}sleep(1);}while(ret == 0);//ret!=0表示子进程结束if(WIFEXITED(status)&&(ret==pid)){printf("wait child 5s success,child exit code is:%d\n",WEXITSTATUS(status));}else{printf("wait child failed.\n");exit(1);}}return 0;
}

运行结果:

非阻塞式等待,就是谁先执行不一定,在此代码中,是父进程先执行的,然后让父进程睡眠1s,从而让子进程执行,子进程执行到sleep(5)时,此时又去执行父进程,但是子进程还没有执行结束,故一直执行while循环,5s过后,又再次遇到sleep(1),又去执行子进程,这时子进程就会结束,父进程继续完成自己的工作

若WIFEXITED(status)为真---->进程正常退出
若WEXITSTATUS(status)>0---->WEXITSTATUS(status)表示子进程的退出码

LInux:进程等待之wait() waitpid()相关推荐

  1. linux 进程等待 wait 、 waitpid

    waitpid() 与 wait() 功能相似,都是用户主进程等待子进程结束或中断. 可用于进程之间的同步 wait 函数原型 pid_t wait(int *status); 函数说明 wait() ...

  2. linux 进程wait,linux 进程等待 wait 、 waitpid(示例代码)

    waitpid() 与 wait() 功能相似,都是用户主进程等待子进程结束或中断. 可用于进程之间的同步 wait 函数原型 pid_t wait(int *status); 函数说明 wait() ...

  3. linux进程等待wait()实例

    在Linux系统中,进程的生命周期内主要包含:进程就绪.进程执行.进程等待和进程退出. 就绪转执行 处于就绪状态的进程,当进程调度程序为之分配了处理机(CPU)后,该进程便由就绪状态转变成执行状态. ...

  4. 【Linux】进程等待wait/waitpid status详解 (非)阻塞等待(代码)

    文章目录 进程等待原因 进程等待方法 wait waitpid 获取子进程status (非)阻塞等待 进程的非阻塞等待方式代码 进程的阻塞等待方式代码 进程等待原因 fork创建了子进程,子进程帮父 ...

  5. Linux 等待进程结束 wait() 和 waitpid()

    若子进程先于父进程结束时,父进程调用wait()函数和不调用wait()函数会产生两种不同的结果: --> 如果父进程没有调用wait()和waitpid()函数,子进程就会进入僵死状态. -- ...

  6. linux的多进程等待,等待进程结束wait()和waitpid()函数

    上一节最后我们说到若子进程先于父进程结束时,父进程调用wait()函数和不调用wait()函数会产生两种不同的结果: --如果父进程没有调用wait()和waitpid()函数,子进程就会进入僵死状态 ...

  7. Linux进程创建fork、进程退出exit()、进程等待waitpid()

    虽然通过标题,我们就轻易的知道了这三个函数的作用,可是,你真的了解这几个函数码?下面让我们来看看这三个函数到底有什么! 一.进程创建fork() 首先,我们来看一看fork()的函数声明: #incl ...

  8. Linux进程3:父进程等待(wait,waitpid)子进程退出并收集子进程退出状态,僵尸进程

    父进程等待(wait,waitpid)子进程退出并收集子进程退出状态 1.父进程为什么要等待子进程退出? 创建子进程目的:------干活 我们要知道干活结束没. 子进程退出状态不被收集,变成僵尸进程 ...

  9. Linux内核中的进程等待与其实现解析

    一.进程等待的概述 进程通过 fork 产生子进程,进程也会死亡,进程退出的时候将会进行内核清理,释放所有进程的资源,资源包括:内存资源,文件资源,信号量资源,共享内存资源,或者引用计数减一,或者彻底 ...

最新文章

  1. 魔兽怀旧服怎么找不到服务器,魔兽世界怀旧服无法连接服务器怎么解决 服务器连接不上解决方法...
  2. matlab变量区表示函数,MATLAB中的工作区,变量和函数
  3. 啥是指标陷阱?很多就出现在你的身边!
  4. 【工作总结】C++ string工具类
  5. 怎么把网页源码家入hexo博客_一款被大厂选用的 Hexo 博客主题
  6. hashmap 存取原理图_HashMap底层实现原理
  7. Asp.net core使用MediatR进程内发布/订阅
  8. jzoj4015-数列【循环节,数论】
  9. 终端不能联网_5G和物联网DDA的关系
  10. 如何让DIV模块随着页面固定和不固定
  11. Handler sendMessage 与 obtainMessage (sendToTarget)比较
  12. 外资企业可以在中国上市吗
  13. 在线教育项目(六)之讲师功能实现
  14. Arm 虚拟硬件与新解决方案或将颠覆物联网产品研发
  15. Istio Egress Gateway出口流量管理
  16. 继续安利两个漫画App
  17. EDM邮件营销的劣势讲解
  18. 【最新版】友价T5交易商城源码 ,10月更新新增自助交易
  19. openlayers 绘制tin数据导文
  20. 火车运输(NOIP2013)

热门文章

  1. macOS 和 Linux 有什么区别?
  2. python网易云音乐下载,可选择歌曲,下载路径
  3. 台式计算机键盘进水了还能用,电脑键盘进水的解决方法
  4. Go实战--golang中使用JWT(JSON Web Token)
  5. 《VR/AR技术与应用》笔记 002
  6. 【微信小程序原生】 上传图片和视频
  7. 微信支付之 内网穿透
  8. 数据分析预测的方法有哪些
  9. 术语解释(PV、UV、QPS、TPS)
  10. 计算机怎样关闭电脑桌面弹窗,永久关闭电脑弹窗广告的三种方法