wait()函数的使用
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status)
功能:等待任意一个子进程结束,如果任意一个子进程结束了,此函数会回收子进程。
参数:int *status
进程退出时的状态信息,传入的是一个int类型的地址,传出参数。
返回值:
-成功:返回被回收的子进程的id
-失败:-1(等所有的子进程都结束后,证明函数调用失败,所以返回-1).
调用wait()函数的进程会被挂起(阻塞),直到它的一个子进程退出或者收到一个不能被忽略的信号才能被唤醒(相当于继续往下执行);
如果没有子进程,函数会立即返回-1;如果子进程已经结束了,也会立即返回-1.
下面的创建了5个fork(),先观察什么结果。
1 #include <stdio.h>2 #include <unistd.h>3 #include <sys/stat.h>4 #include <unistd.h>5 int main()6 {7 pid_t pid;8 for(int i=0;i<5;i++)9 {10 pid=fork();11 if(pid==0)12 {13 break;14 }15 }16 if(pid>0)17 {18 while(1)19 {20 printf("parent:%d\n",getpid());21 sleep(1);22 }23 }24 else if(pid==0)25 {26 printf("child:%d\n",getpid());27 }28 return 0;2930 }
运行结果如下:
child:54384
child:54385
parent:54383
child:54387
child:54388
child:54386
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
parent:54383
通过观察就可以发现,通过调用五次fork()函数,出现了五次子进程id,随即就都是父进程了,也就是说出现五次子进程id后就死掉了,也可以通过ps aux来查看
Z+呈现出僵死的状态,如果CTRL+C,重新查看ps aux就不会出现僵死的状态了,此时就会被进程号为1的init给回收了。
接下来,加入我们的主角wait(),看看有什么效果,让我们拭目以待
1 #include <stdio.h>2 #include <unistd.h>3 #include <sys/stat.h>4 #include <unistd.h>5 #include <sys/wait.h>6 int main()7 {8 pid_t pid;9 for(int i=0;i<5;i++)10 {11 pid=fork();12 if(pid==0)13 {14 break;15 }16 }17 if(pid>0)18 {19 while(1)20 {21 printf("parent:%d\n",getpid());22 int ret=wait(NULL);23 printf("child die,pid=%d\n",ret);24 sleep(1);25 }26 }27 else if(pid==0)28 {29 while(1)30 {31 printf("child:%d\n",getpid());32 sleep(1);33 }34 }35 return 0;3637 }
注意观察,我在父进程中加入了wait()函数,因为调用wait()函数的进程会被挂起(阻塞),所以当程序运行到时,父进程就被挂起了(相当于退出),然后去运行子进程了
通过截图可以看出父进程只运行了一次。如果此时我杀死一个进程kill -9 5417,那么出现了
说明在刚刚父进程阻塞的地方现在变得不阻塞了,将继续往下运行,如果全部杀死后,就没有子进程了,那么此时就变成了-1.自己可以动手操作一下。
另外,还有一些退出信息相关的宏函数
WIFEXITED(status)-->为真-->调用WEXITSTATUS(status)-->得到 子进程 退出值。
(作用:判断是不是正常退出)
WIFSIGNALED(status)-->为真-->调用WTERMSIG(status)-->得到 导致子进程异常终止的信号编号。
(作用:判断被哪个信号给干掉了)
接下来我们一步一步操作(只插入主函数)
7 int main()8 {9 pid_t pid;10 for(int i=0;i<5;i++)11 {12 pid=fork();13 if(pid==0)14 {15 break;16 }17 }18 if(pid>0)19 {20 while(1)21 {22 printf("parent:%d\n",getpid());23 int st;24 int ret=wait(&st);25 if(ret==-1)26 {27 break;28 }29 if(WIFEXITED(st))30 {31 printf("退出的状态码:%d\n",WEXITSTATUS(st));32 }33 if(WIFSIGNALED(st))34 {35 printf("被那个信号给干掉了:%d\n",WTERMSIG(st));36 }37 printf("child die,pid=%d\n",ret);38 sleep(1);39 }40 }41 else if(pid==0)42 {43 printf("child:%d\n",getpid());44 sleep(1);45 exit(0);46 }47 return 0;4849 }
运行结果:退出状态码是由exit(0)决定的,如果exit(1).则退出状态码就是1.
当我把子进程放进死循环中,然后kill -9 子进程id,此时变成了
获取了被哪个信号给干掉了。真棒
wait()函数的使用相关推荐
- 数据库中自定义排序规则,Mysql中自定义字段排序规则,Oracle中自定义字段排序规则,decode函数的用法,field函数的用法
数据库中自定义排序 场景:有一张banner表,表中有一个status字段,有0, 1, 2三个状态位,我想要 1,0,2的自定义排序(这里是重点),然后再进行之上对sequence字段进行二次排序( ...
- Mysql函数group_concat、find_in_set 多值分隔字符字段进行数据库字段值翻译
Mysql函数group_concat.find_in_set进行数据库字段值翻译 场景 配方表:记录包含的原料 sources表示原料,字段值之间用逗号分隔 原料表:对应原料id和原料名称 现需要查 ...
- C++ 笔记(34)— C++ exit 函数
当遇到 main 函数中的 return 语句时,C++ 程序将停止执行.但其他函数结束时,程序并不会停止.程序的控制将返回到函数调用之后的位置.然而,有时候会出现一些非常少见的情况,使得程序有必要在 ...
- C++ 笔记(30)— 友元函数与友元类
我们知道类的私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行.这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书写的麻烦. ...
- 浅显易懂 Makefile 入门 (07)— 其它函数(foreach 、if、call、origin )
1. foreach 函数 foreach 函数定义如下: $(foreach <var>,<list>,<text>) 函数的功能是:把参数 <list&g ...
- 浅显易懂 Makefile 入门 (06)— 文件名操作函数(dir、notdir、suffix、basename、addsuffix、addperfix、join、wildcard)
编写 Makefile 的时候,很多情况下需要对文件名进行操作.例如获取文件的路径,去除文件的路径,取出文件前缀或后缀等等. 注意:下面的每个函数的参数字符串都会被当作或是一个系列的文件名来看待. 1 ...
- Go 学习笔记(65)— Go 中函数参数是传值还是传引用
Go 语言中,函数参数传递采用是值传递的方式.所谓"值传递",就是将实际参数在内存中的表示逐位拷贝到形式参数中.对于像整型.数组.结构体这类类型,它们的内存表示就是它们自身的数据内 ...
- Go 学习笔记(61)— Go 高阶函数、函数作为一等公民(函数作为输入参数、返回值、变量)的写法
函数在 Go 语言中属于"一等公民(First-Class Citizen)"拥有"一等公民"待遇的语法元素可以如下使用 可以存储在变量中: 可以作为参数传递给 ...
- C++ 笔记(26)— 主函数 main(int argc, char *argv[]) 参数说明
带形参的 main 函数,如 int main( int argc, char* argv[], char **env ) 是 UNIX .Linux 以及 Mac OS 操作系统中 C/C++ 的 ...
- OpenCV 笔记(09)— 常用的数据结构和函数(Vec、Point、Scalar、Size、Rect、cvtColor)
1. Vec 对象类型 Vec 是一个主要用于数值向量的模板类.我们可以定义向量的类型和组件的数量: Vec<double, 19> myVector 我们还可以使用任何的预定义类型: t ...
最新文章
- Windows下RabbitMQ安装及注意事项
- 非常棒的 「Sublime Text 配色/主题」与「编程字体」
- 1.16 字符串的加密解密
- 用u盘做引导,往硬盘中安装ubuntu
- ZOJ - 2972 Hurdles of 110m(记忆化搜索/动态规划)
- 伦敦科学博物馆用百年智慧打造的一套探索书,拓展孩子的科学、数学和艺术思维...
- 数据结构——图-最短路径长度中最大的一个
- java web开发之上机指导(2)
- vue 在js 文件中使用store_vue 如何在 .js 文件引入 store
- 计算机组成原理写一个运算器,计算机组成原理运算器的实现实验报告.doc
- LotusScript (转)
- java7-3 继承
- [C/C++]Windows下的getch函数实现
- 计算机网络数据通信部分之网络层IP报文格式解析
- 有没有免费又好用的云桌面系统?
- Re:PyQt5 从零开始的MVC开发模式规划
- 电池充电IC市场现状研究分析与发展前景预测报告
- python多线程爬取王者荣耀高清壁纸过程
- 运算符优先级记忆口诀
- Python编程|手把手教植物大战僵尸,代码开源
热门文章
- python配对t检验_置信度计算——t检验(配对样本t检验,AB实验置信度),T
- 20190105 地中海气候
- 【XSY3330】地中海气候(思维)
- csdn博客排行榜 第一名
- 服务器出现信号问题,网络故障中出现的丢包是什么意思?什么又是丢包率?
- android 自定义表情包,快速打造 Android 自定义表情库
- nfs-ganesha(用户态NFS)编译、安装和使用
- php 单词拼写检查,PHP实例:PHP的拼写检查函数库
- 2012敏捷之旅苏州站活动将于2012年11月3日在西交利物浦大学举办
- JSP+access手机销售系统免费LW+系统