LInux:进程等待之wait() waitpid()
进程等待
之前说,子进程退出,父进程如果不管不顾,就可能造成“僵尸进程”的问题,进而造成内存泄露,进而,进程一旦变成僵尸状态,杀人不眨眼的”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()相关推荐
- linux 进程等待 wait 、 waitpid
waitpid() 与 wait() 功能相似,都是用户主进程等待子进程结束或中断. 可用于进程之间的同步 wait 函数原型 pid_t wait(int *status); 函数说明 wait() ...
- linux 进程wait,linux 进程等待 wait 、 waitpid(示例代码)
waitpid() 与 wait() 功能相似,都是用户主进程等待子进程结束或中断. 可用于进程之间的同步 wait 函数原型 pid_t wait(int *status); 函数说明 wait() ...
- linux进程等待wait()实例
在Linux系统中,进程的生命周期内主要包含:进程就绪.进程执行.进程等待和进程退出. 就绪转执行 处于就绪状态的进程,当进程调度程序为之分配了处理机(CPU)后,该进程便由就绪状态转变成执行状态. ...
- 【Linux】进程等待wait/waitpid status详解 (非)阻塞等待(代码)
文章目录 进程等待原因 进程等待方法 wait waitpid 获取子进程status (非)阻塞等待 进程的非阻塞等待方式代码 进程的阻塞等待方式代码 进程等待原因 fork创建了子进程,子进程帮父 ...
- Linux 等待进程结束 wait() 和 waitpid()
若子进程先于父进程结束时,父进程调用wait()函数和不调用wait()函数会产生两种不同的结果: --> 如果父进程没有调用wait()和waitpid()函数,子进程就会进入僵死状态. -- ...
- linux的多进程等待,等待进程结束wait()和waitpid()函数
上一节最后我们说到若子进程先于父进程结束时,父进程调用wait()函数和不调用wait()函数会产生两种不同的结果: --如果父进程没有调用wait()和waitpid()函数,子进程就会进入僵死状态 ...
- Linux进程创建fork、进程退出exit()、进程等待waitpid()
虽然通过标题,我们就轻易的知道了这三个函数的作用,可是,你真的了解这几个函数码?下面让我们来看看这三个函数到底有什么! 一.进程创建fork() 首先,我们来看一看fork()的函数声明: #incl ...
- Linux进程3:父进程等待(wait,waitpid)子进程退出并收集子进程退出状态,僵尸进程
父进程等待(wait,waitpid)子进程退出并收集子进程退出状态 1.父进程为什么要等待子进程退出? 创建子进程目的:------干活 我们要知道干活结束没. 子进程退出状态不被收集,变成僵尸进程 ...
- Linux内核中的进程等待与其实现解析
一.进程等待的概述 进程通过 fork 产生子进程,进程也会死亡,进程退出的时候将会进行内核清理,释放所有进程的资源,资源包括:内存资源,文件资源,信号量资源,共享内存资源,或者引用计数减一,或者彻底 ...
最新文章
- 魔兽怀旧服怎么找不到服务器,魔兽世界怀旧服无法连接服务器怎么解决 服务器连接不上解决方法...
- matlab变量区表示函数,MATLAB中的工作区,变量和函数
- 啥是指标陷阱?很多就出现在你的身边!
- 【工作总结】C++ string工具类
- 怎么把网页源码家入hexo博客_一款被大厂选用的 Hexo 博客主题
- hashmap 存取原理图_HashMap底层实现原理
- Asp.net core使用MediatR进程内发布/订阅
- jzoj4015-数列【循环节,数论】
- 终端不能联网_5G和物联网DDA的关系
- 如何让DIV模块随着页面固定和不固定
- Handler sendMessage 与 obtainMessage (sendToTarget)比较
- 外资企业可以在中国上市吗
- 在线教育项目(六)之讲师功能实现
- Arm 虚拟硬件与新解决方案或将颠覆物联网产品研发
- Istio Egress Gateway出口流量管理
- 继续安利两个漫画App
- EDM邮件营销的劣势讲解
- 【最新版】友价T5交易商城源码 ,10月更新新增自助交易
- openlayers 绘制tin数据导文
- 火车运输(NOIP2013)