Linux学习之系统编程3(进程及wait函数)

写在前面:

我的Linux的学习之路非常坎坷。第一次学习Linux是在大一下的开学没多久,结果因为不会安装VMware就无疾而终了,可以说是没开始就失败了。第二次学习Linux是在大一下快放暑假(那个时候刚刚过完考试周),我没什么事做就又重拾Linux,不服输的我选择再战Linux,这一次学习还算顺利,虽然中间有些小插曲但是不影响整体学习进度, 我看着B站上的视频一点点学习Linux,基本上把Linux的基础指令学完了。学完之后我又遇到问题了,视频基本上到这就结束了,而我却不知道下一步该学什么,于是就没怎么碰Linux,结果没过多长时间我就把学的Linux指令忘的一干二净。现在是我第三次学习Linux,我决定重新开始学Linux,同时为了让自己学习的效果更好,我选择以写blog的形式逼迫自己每天把学习到的Linux知识整理下来。这也就是我写这个系列blog的原因。


wait&waitpid函数

1

我们先来看wait函数

传入参数:

一个int类型的指针,各位童鞋看名字应该就可以猜出来是表示状态信息的。没错,wstate就是表示回收的子进程 信息,我们可以调用一些宏函数去判断子进程的信息(详细的后面我在说)。当然,你也可以传NULL,也不会报错。

返回值:
  • 成功,回收进程的pid
  • 失败,-1,设置errno
函数的作用
  1. 阻塞等待子进程退出
  2. 清理子进程残留在内核的 pcb 资源
  3. 通过传出参数,得到子进程结束状态
利用宏函数获取子进程信息
  • WIFEXITED(status)——>为真,子进程正常终止。再次调用WSTATUS(status)——>得到子进程退出值
  • WIFSIGNALED(status)——>为真,子进程被信号终止。调用WTERMSIG(status)——>得到子进程异常终止的的信号编号。

一个进程终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的 PCB 还保留着,内
核在其中保存了一些信息:如果是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程
终止的信号是哪个。这个进程的父进程可以调用wait或者waitpid获取这些信息,然后彻底清除掉
这个进程。我们知道一个进程的退出状态可以在 shell 中用特殊变量$?查看,因为 shell 是它的父
进程,当它终止时,shell 调用 wait 或者waitpid得到它的退出状态,同时彻底清除掉这个进程。

举个栗子

源代码:

#include<stdio.h>
#include<sys/wait.h>
#include<unistd.h>
#include<string.h>int main()
{pid_t pid,wpid;int state;pid=fork();if(pid==0){printf("I'm child,my pid is %d\n",getpid());sleep(3);printf("child go to die\n");}else if(pid>0){wpid=wait(&state);if(wpid>0)printf("i am parent,wait child id is %d,wait  successfully\n",wpid);elseperror("wait error");}return 0;
}

效果:
2


接着看waitpid函数

3

传入参数
  • pid,有四种可能的值:
    • <-1:等待回收任何组id(gid)等于该值的绝对值的子进程。(manpage原文:meaning wait for any child process whose process group ID is equal to the absolute value of pid.)
    • -1:等待回收任意一个子进程。(manage原文:meaning wait for any child process.)
    • 0:等待回收任意一个组id和该进程组id一致的子进程。(manpage原文:meaning wait for any child process whose process group ID is equal to that of the calling process at the time of the call to waitpid())
    • <0:等待回收指定pid的子进程(这一种是用的最多的)。(manpage原文:meaning wait for the child whose process ID is equal to the value of pid.)
  • status:(传出) 回收进程的状态。
  • options:一般默认是阻塞,即一直等待直到回收一个子进程为止。也可以指定为WNOHANG 指定回收方式为,非阻塞。
返回值:
  • >0: 表成功回收的子进程 pid
  • 0 : 函数调用时, 参 3 指定了 WNOHANG, 并且,没有子进程结束。
  • -1: 失败。errno
举个栗子

我们演示一个小demo,之前我们循环创建过5个子进程,我们这次就来回收指定子进程(下面以回收第三个子进程为例)。

错误演示

源代码:

#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>int main()
{pid_t pid,wpid;int i;for(i=0;i<5;i++){if(fork()==0){if(2==i)pid=getpid();break;}}if(5==i){sleep(5);printf("--------in parent , before waitpid, pid= %d\n", pid);wpid(pid,NULL,0);printf("I'm parent, wait a child finish : %d \n", wpid);}else{sleep(i);printf("I'm %dth child, pid= %d\n", i+1, getpid());}return 0;
}				

效果:
3

错误分析:
上面的代码看似非常对,我们用pid来获取第三个子进程的id,然后让父进程使用waitpid来回收。但是,再仔细看,我们是在子进程把第三个子进程的id赋值给变量pid,但是由于父子进程间遵循的是"读时共享,写时复制",所以对于父进程中变量pid还是没有变,还是0.

正确演示

源代码:

#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/wait.h>int main()
{pid_t pid,wpid,tpid;int i;for(i=0;i<5;i++){pid=fork();if(0==pid)break;if(2==i)tpid=pid;}if(5==i){sleep(5);wpid=waitpid(tpid,NULL,0);printf("tpid=%d\n",tpid);if(wpid==-1){perror("waitpid error");exit(1);}printf("i am parent,wait child id is %d\n",wpid);}else{sleep(i);printf("I am %dth child,my pid is %d\n",i+1,getpid());}return 0;
}

效果:
4

waitpid回收多个子进程

首先我们要无论是wait还是waitpid每一次调用都只能回收一个子进程
源代码:

#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>int main()
{int i;pid_t pid,wpid;for(i=0;i<5;i++){pid=fork();if(!pid)break;}if(5==i){while((wpid=wait(NULL))!=-1){printf("wait child pid is %d\n",wpid);}}else{sleep(i);printf("i am %dth child,my pid is %d\n",i+1,getpid());}return 0;
}

效果:
5

利用宏函数判断子进程返回状态

源代码:

#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>int main()
{pid_t pid,wpid;int state;pid=fork();if(pid==0){printf("i am child,my pid is %d\n",getpid());sleep(15);printf("i am going to die\n");}else{wpid=wait(&state);if(WIFEXITED(state))printf("i am parent,my child was terminal normally, child's pid is %d\n",wpid);else if(WIFSIGNALED(state))printf("my child was terminaled with signal %d,child's pid is %d\n",WTERMSIG(state),wpid);}return 0;
}

效果:
自然终止
6
被信号终止
7


写在最后

个人亲身经验:我们学习的一系列Linux命令,一定要自己亲手去敲。不要只是看别人敲代码,不要只是停留在眼睛看,脑袋以为自己懂了,等你实际上手去敲会发现许许多多的这样那样的问题。正可谓“键盘敲烂,月薪过万


如果你觉得我写的题解还不错的,请各位王子公主移步到我的其他题解看看

  1. 数据结构与算法部分(还在更新中):
  • C++ STL总结 - 基于算法竞赛(强力推荐
  • 动态规划——01背包问题
  • 动态规划——完全背包问题
  • 动态规划——多重背包问题
  • 动态规划——分组背包问题
  • 动态规划——最长上升子序列(LIS)
  • 二叉树的中序遍历(三种方法)
  • 最长回文子串
  • 最短路算法——Dijkstra(C++实现)
  • 最短路算法———Bellman_Ford算法(C++实现)
  • 最短路算法———SPFA算法(C++实现)
  • 最小生成树算法———prim算法(C++实现)
  • 最小生成树算法———Kruskal算法(C++实现)
  • 染色法判断二分图(C++实现)
  1. Linux部分(还在更新中):
  • Linux学习之初识Linux
  • Linux学习之命令行基础操作
  • Linux学习之基础命令(适合小白)
  • Linux学习之权限管理和用户管理
  • Linux学习之制作静态库和动态库
  • Linux学习之makefile
  • Linux学习之系统编程1(关于读写系统函数)

✨🎉总结

“种一颗树最好的是十年前,其次就是现在”
所以,
“让我们一起努力吧,去奔赴更高更远的山海”
在这里插入图片描述
如果有错误❌,欢迎指正哟😋

🎉如果觉得收获满满,可以动动小手,点点赞👍,支持一下哟🎉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/592614.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes 集群搭建(新人白嫖青云服务器) 一个master节点+两个工作节点

文章目录 1&#xff0c; 购买青云服务器&#xff08;白嫖&#xff09;2&#xff0c;创建 VPC3&#xff0c;连接测试4&#xff0c;安装 docker4.1&#xff0c;安装docker 20.10.74.2&#xff0c;配置加速镜像 5&#xff0c;安装 Kubernetes5.1&#xff0c;要求5.2&#xff0c;设…

CRM市场营销管理功能,如何进行客户细分和数据分析?

CRM管理系统中的营销管理模块&#xff0c;它的锋芒常被销售管理所掩盖&#xff0c;但对于企业的业务来说同样重要。营销部门虽然不像销售人员一样直接面对客户&#xff0c;却是挖掘线索、商机的重要角色。CRM在市场营销领域的关键功能包括&#xff1a;营销漏斗、客户细分、营销…

关于“Python”的核心知识点整理大全50

目录 python_repos.py 17.1.6 概述最受欢迎的仓库 python_repos.py 17.1.7 监视 API 的速率限制 注意 17.2 使用 Pygal 可视化仓库 python_repos.py 17.2.1 改进 Pygal 图表 python_repos.py 往期快速传送门&#x1f446;&#xff08;在文章最后&#xff09;&#xf…

抽象类和接口的区别

抽象类和接口的区别&#xff1a; 抽象类&#xff08;Abstract Class&#xff09;&#xff1a; 抽象类是一种不能被实例化的类&#xff0c;它只能被用作其他类的父类&#xff08;基类&#xff09;。抽象类可以包含抽象方法和非抽象方法。抽象方法是没有具体实现的方法&#xf…

2020年认证杯SPSSPRO杯数学建模B题(第二阶段)分布式无线广播全过程文档及程序

2020年认证杯SPSSPRO杯数学建模 B题 分布式无线广播 原题再现&#xff1a; 以广播的方式来进行无线网通信&#xff0c;必须解决发送互相冲突的问题。无线网的许多基础通信协议都使用了令牌的方法来解决这个问题&#xff0c;在同一个时间段内&#xff0c;只有唯一一个拿到令牌…

医院信息系统集成平台—数据交换层

医院集成平台核心是数据交换总线,这解决当前大部分医院最关注的电子病历与移动医疗等业务系统接口交互共享及消息数据状态同步(消息一体化机制)等问题。集成平台主要包括业务数据集并提供相应的标准处理接口API(含数据采集与数据发布查询更新),同时提供相应的适配器服务来…

20240102使用python3将视频切片改名之后合并

20240102使用python3将视频切片改名之后合并 2024/1/2 22:12 缘起&#xff1a;将迅雷下载的视频切片排序之后再通过ffmpeg合并&#xff01;https://pri-cdn-tx.xiaoeknow.com/app1cE7gLFM1187/confusion_index/1703599111EAPoRE.m3u8?signf17e1a2cc0ddd77801f3c5110116369e&am…

C++ //习题14.2 将例14.3程序改为下面的程序,请分析执行过程,写出运行结果。并指出由于异常处理而调用了哪些析构函数。

C程序设计 &#xff08;第三版&#xff09; 谭浩强 习题14.2 习题14.2 将例14.3程序改为下面的程序&#xff0c;请分析执行过程&#xff0c;写出运行结果。并指出由于异常处理而调用了哪些析构函数。 IDE工具&#xff1a;VS2010 Note: 使用不同的IDE工具可能有部分差异。 代…

Qt:自定义一个好看的等待提示Ui控件

一、2024 永不卡顿 爱的魔力它转圈圈~ 等待样式控件是我们在做UI时出场率还挺高的控件之一&#xff0c;通常情况下有如下的几种实现方式&#xff1a; 1> 获取一张gif的资源图&#xff0c;然后使用QMovie 在一个QLabel 控件上加载显示gif的waiting等待动态。 2> 自定义绘图…

Linux 进程(五) 调度与切换

概念准备 当一个进程放在cpu上运行时&#xff0c;是必须要把进程的代码跑完才会进行下一个进程吗&#xff1f;答案肯定是 不对。现在的操作系统都是基于时间片轮转执行的。 时间片&#xff08;timeslice&#xff09;又称为“量子&#xff08;quantum&#xff09;”或“处理器片…

计算机网络【Cookie和session机制】

会话&#xff08;Session&#xff09;跟踪是Web程序中常用的技术&#xff0c;用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份&#xff0c;Session通过在服务器端记录信息确定用户身份。 本章将系统地讲述Cookie与Sess…

【Pytorch】学习记录分享11——PyTorch GAN对抗生成网络

PyTorch GAN对抗生成网络 0. 工程实现1. GAN对抗生成网络结构2. GAN 构造损失函数&#xff08;LOSS&#xff09;3. GAN对抗生成网络LOSS损失函数说明 0. 工程实现 1. GAN对抗生成网络结构 2. GAN 构造损失函数&#xff08;LOSS&#xff09; LOSS公式与含义&#xff1a; LOSS…

javascript 常见工具函数(四)

31.RGB值和十六进制值之间的转换&#xff1a; &#xff08;1&#xff09;十六进制的颜色转为 RGB格式&#xff1a; /*16进制颜色转为RGB格式*/String.prototype.colorRgb function () {var sColor this.toLowerCase();if (sColor && reg.test(sColor)) {if (sColor.l…

C++初阶——类与对象

目录 C宏函数 在使用宏函数时&#xff0c;有几个常见的错误需要注意&#xff1a; 宏函数在某些情况下有以下优势&#xff1a; 1.C宏函数 在 C 中&#xff0c;宏函数&#xff08;Macro Function&#xff09;是使用预处理器定义的宏&#xff08;Macro&#xff09;&#xff0…

初识Linux下进程

&#x1f30e;初识进程 初识进程 简单认识一下进程 如何管理进程 进程属性信息 内核运行队列 查看进程 通过系统调用获取进程标识符       父子进程       查看运行中的进程 总结 前言&#xff1a; 我们在电脑上点开的一个个应用&#xff0c;其实就是一个个进程&am…

初识Java并发,一问读懂Java并发知识文集(4)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

智能标志桩:防盗防外物入侵_图像监测_态势感知_深圳鼎信

智能标志桩是一种新型的智能化标志设备&#xff0c;主要用于标识地下管道的位置、类型等&#xff0c;起警示作用。这与传统的标志桩大不相同&#xff0c;物联网的高速发展赋予了智能标志桩科技的力量&#xff0c;使它可以连接互联网&#xff0c;还具备图像监控的功能&#xff0…

2024年P气瓶充装证考试题库及P气瓶充装试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年P气瓶充装证考试题库及P气瓶充装试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大纲随机出的P气…

C++Qt6 多种排序算法的比较 数据结构课程设计 | JorbanS

一、 问题描述 在计算机科学与数学中&#xff0c;一个排序算法&#xff08;英语&#xff1a;Sorting algorithm&#xff09;是一种能将一串资料依照特定排序方式排列的算法。最常用到的排序方式是数值顺序以及字典顺序。有效的排序算法在一些算法&#xff08;例如搜索算法与合…

Linux系统操作常用指令

打开终端&#xff1a; ctrlshiftt:切换标签 ctrlshiftn:新增窗口 Linux命令大全(超详细版)_第二范式的博客-CSDN博客 VMware运行时以管理员身份运行&#xff0c;可以避免许多问题。 输入法切换 ctrl 空格 放大终端&#xff1a;ctrlshift"" 缩小终端&#xff1a;ctrl“…