系统编程-进程-wait、waitpid和WIFEXITED系列宏 超级详解
1. wait、waitpid 函数简介

补充:对于waitpid,如果返回值为0,表示指定去等待的子进程尚未结束。

该系列宏的使用方法展示:

PART1
实验思路:
使用wait系统调用让父进程给子进程收尸,并获取子进程的返回值。
同时,正常终止。
直接打印获取的返回值会与实际返回的值不一样,进而引出检查WIFEXITED/WEXITSTATUS(status)等系列宏。
实验1: waitpid或waitpid,使用展示, 同时,直接使用printf打印出子进程的返回值
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h> int main(void)
{
int status = 0;
pid_t pid;
printf("pid: %ld\n", (long)getpid()); pid = fork();
if (pid < 0) {
printf("fork error");
}
else if (pid == 0) {
sleep(2);
printf("pid: %ld, ppid: %ld\n", (long)getpid(), (long)getppid()); exit(3);
} if (waitpid(pid, &status, 0) != pid) { // if (wait(&status) != pid) { 这里也可以使用wait, 我这里对waitpid的使用也是阻塞方式的
printf("waitpid error");
}
else{
printf("status =%d\n", status);
} return 0;
}
编译运行:

可以看到,本实验中的waitpid在2秒后才返回,成功替子进程收尸。
但是我们打印的status不对劲,我们的代码内子进程返回值是3, 打印的768是什么鬼? 于是我们做实验2,使用WIFEXITED/WEXITSTATUS(status)等系列宏。
实验2: 在实验1的基础上新增使用WIFEXITED/WEXITSTATUS(status)等系列宏
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h> void out_status(int status){ if(WIFEXITED(status)){
printf("normnal exit: %d \n", WEXITSTATUS(status)); }else if(WIFSIGNALED(status)){
printf("abnormal term: %d \n", WTERMSIG(status)); }else if(WIFSTOPPED(status)){
printf("stopped sig: %d \n", WSTOPSIG(status)); }else{
printf("unknow sig");
}
} int main(void)
{
int status = 0;
pid_t pid;
printf("pid: %ld\n", (long)getpid()); pid = fork();
if (pid < 0) {
printf("fork error");
}
else if (pid == 0) {
sleep(2);
printf("pid: %ld, ppid: %ld\n", (long)getpid(), (long)getppid()); exit(3);
} if (wait(&status) != pid) {
printf("waitpid error");
}
else{
printf("status =%d\n", status);
out_status(status);
} return 0;
}
编译运行:

到此为止,wait和waitpid的阻塞式的使用,以及子进程正常返回的实验,顺利完成。
我们还需要判断子进程的异常终止、和判断子进程是否暂停了, 所以我们接着来完善这部分的知识体系。
PART2
子进程异常终止 - 实验:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h> void out_status(int status){ if(WIFEXITED(status)){
printf("normnal exit: %d \n", WEXITSTATUS(status)); }else if(WIFSIGNALED(status)){
printf("abnormal term: %d \n", WTERMSIG(status)); }else if(WIFSTOPPED(status)){
printf("stopped sig: %d \n", WSTOPSIG(status)); }else{
printf("unknow sig");
}
} int main(void)
{
int status = 0;
pid_t pid;
printf("pid: %ld\n", (long)getpid()); pid = fork();
if (pid < 0) {
printf("fork error");
}
else if (pid == 0) {
sleep(2);
printf("pid: %ld, ppid: %ld\n", (long)getpid(), (long)getppid()); // 我们可以在子进程内新增几行除零运算的代码,来引发子进程异常终止
int i=89, j=0;
int k = i/j;
printf("k=%d \n", k); exit(3);
} if (wait(&status) != pid) {
printf("waitpid error");
}
else{
printf("status =%d\n", status);
out_status(status);
} return 0;
}
编译运行,同时查看下8号信号是什么信号


由度娘知,SIGFPE是系统发出的针对进程内进行非法运算的一个信号。
至此,我们又多了一个技能,可以判断子进程是否被异常终止,以及具体的异常终止原因了!
PART3
判断子进程是否暂停了
要判断子进程是否暂停了,不能使用wait,只能使用waitpid,而且需要加上特定的参数选项。

重申下列知识点:

由此可见,
waitpid函数的最后一个参数配置为WUNTRACED,则后续判断子进程返回状态时,需要结合WIFSTOPED宏、
waitpid函数的最后一个参数配置为WCONTINUED,则后续判断子进程返回状态时,需要结合WIFCONTINUED宏。
实验环节
实验目的:判断子进程是否暂停了、是否又继续运行起来了
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h> void out_status(int status){ if(WIFEXITED(status)){
printf("normnal exit: %d \n", WEXITSTATUS(status)); }else if(WIFSIGNALED(status)){
printf("abnormal term: %d \n", WTERMSIG(status)); }else if(WIFSTOPPED(status)){
printf("stopped sig: %d \n", WSTOPSIG(status)); }else if(WIFCONTINUED(status)){
printf("WIFCONTINUED \n");
}else{
printf("unknow sig \n");
}
} int main(void)
{
int status = 0;
pid_t pid;
printf("pid: %ld\n", (long)getpid()); pid = fork();
if (pid < 0) {
printf("fork error");
}
else if (pid == 0) {
int i=0;
printf("--child process begins running, pid=%d\n", getpid());
while(1){
i++;
if(i == 1000000)
i=0;
}
} pid = waitpid(pid, &status, WUNTRACED);
printf("pid=%d \n", pid);
out_status(status); pid = waitpid(pid, &status, WCONTINUED);
printf("pid=%d \n", pid);
out_status(status); return 0;
}
运行:
一个终端内:

另一个终端内:

分析:
先向子进程发送19号信号,会使得父进程解除阻塞,获取到子进程被暂停了这一信息。
之后父进程又再次调用阻塞接口,等待子进程继续运行,当在该终端内发送18号信号,即可让子进程继续运行,从而使得父进程解除阻塞,获得子进程又继续运行了这一信息。
补充:
19) SIGSTOP 20) SIGTSTP
19号信号和29号信号的相同点: 都可以使得进程暂停,并且收到SIGCONT信号后可以让进程重新运行。
19号信号和29号信号的不同点: SIGSTOP不可以捕获(即使用信号处理函数)。
.
系统编程-进程-wait、waitpid和WIFEXITED系列宏 超级详解的更多相关文章
- Linux系统编程@进程通信(一)
		
进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统 ...
 - linux系统编程-进程
		
进程 现实生活中 在很多的场景中的事情都是同时进行的,比如开车的时候 手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的: 如下是一段视频,迈克杰克逊的一段视频: http://v.youku.com ...
 - nginx高性能WEB服务器系列之四配置文件详解
		
nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...
 - mongo 3.4分片集群系列之五:详解平衡器
		
这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...
 - mongo 3.4分片集群系列之六:详解配置数据库
		
这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...
 - legend3---Windows 7/8/10 系统下Laravel框架的开发环境安装及部署详解(Vagrant + Homestead)
		
legend3---Windows 7/8/10 系统下Laravel框架的开发环境安装及部署详解(Vagrant + Homestead) 一.总结 一句话总结: 1.安装的话就是下载好git,va ...
 - Hexo系列(二) 配置文件详解
		
Hexo 是一款优秀的博客框架,在使用 Hexo 搭建一个属于自己的博客网站后,我们还需要对其进行配置,使得 Hexo 更能满足自己的需求 这里所说的配置文件,是位于站点根目录下的 _config.y ...
 - css3系列之transform详解translate
		
translate translate这个参数的,是transform 身上的,那么它有什么用呢? 其实他的作用很简单,就是平移,参考自己的位置来平移 translate() translateX() ...
 - Spring Boot 2.x基础教程:进程内缓存的使用与Cache注解详解
		
随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...
 - ThreeJS系列1_CinematicCameraJS插件详解
		
ThreeJS系列1_CinematicCameraJS插件详解 接着上篇 ThreeJS系列1_CinematicCameraJS插件介绍 看属性的来龙去脉 看方法作用 通过调整属性查看效果 总结 ...
 
随机推荐
- oeasy教您玩转vim - 17 - # 向上向下
			
向上向下 回忆上节课内容 和 f 相关的是跳到 向 前 跳到是 f 向 后 跳到是 F 和 t 相关的是贴靠 向 前 贴靠是 t 向 后 贴靠是 T 和 小写 相关的是 向前 向前 跳跃是 f 向前 ...
 - 【jQuery学习日记】从入门到再入门
			
1,jQuery介绍 jQuery 是一个 JavaScript 库. jQuery 极大地简化了 JavaScript 编程. 2,入门jQuery jQuery有两大核心:jQuery核心函数和j ...
 - Django Template层之Template概述
			
Django Template层之Template概述 by:授客 QQ:1033553122 实践环境 Python版本:python-3.4.0.amd64 下载地址:https://www.py ...
 - springboot集成minIO
			
文件系统:负责管理和存储文件的系统软件.操作系统通过文件系统提供的接口去存取文件,用户通过操作系统访问磁盘上的文件 minIO:轻量级服务分布式文件系统,适合存储非机构化数据.采用去中心化共享架构,结 ...
 - 2023/4/20 SCRUM个人博客
			
1.我昨天的任务 学习了PYQT5的部分控件,例如按钮,文本框,文本编辑框,并了解了一些基础布局以及部分对窗口的自定义实现 2.遇到了什么困难 无法理解信号和槽的概念 3.我今天的任务 学习信号和槽的 ...
 - 【JS】04 DOM 文档对象模型 P1 查找元素、改变内容、绑定事件
			
什么是DOM? Document Object Model 文档指的是HTML文档 当浏览器打开一个网页的时候,实际上把HTML文档读取到内存中进行解析 整个HTML文档被封装为document文档对 ...
 - 【FastDFS】环境搭建 02 测试
			
自带工具测试: 编辑客户端配置文件: vim client.conf 配置完成后,随便上传一个图片到root目录下 运行FastFDS文件上传程序,并将客户端配置文件作为加载参数1,要上传的图片文件位 ...
 - 如何理解计算机类论文、机器学习论文、人工智能AI论文中的“soft”和“hard”呢?
			
如何理解计算机类论文.机器学习论文.人工智能AI论文中的"soft"和"hard"呢? 最近在看论文中总看到带有"soft"和"h ...
 - Jax框架:通过显存分析判断操作是否进行jit编译
			
相关: https://jax.readthedocs.io/en/latest/device_memory_profiling.html 代码: import jax import jax.nump ...
 - 清华镜像源、阿里镜像源全部失效后怎么办 —— conda 服务器代理配置 —— Jax框架的安装
			
相关: conda 服务器代理配置 最近在用anaconda安装Jax框架,发现直接使用官方源下载的速度十分的慢,估计要需20个小时才能下载完成,对于这种情况第一个感觉就是使用镜像源来进行下载. 但是 ...