【Linux】进程等待

什么是进程等待?

通过系统用wait/waitpid,来进行对子进程进行状态检测与回收的功能!


为什么要有进程等待?

  1. ‘僵尸进程’无法被杀死,只能通过进程等待来回收,进而解决内存泄漏问题。
  2. 父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息-----子进程运行完成,结果对还是不对, 或者是否正常退出。(父进程可以关心也可以不关心,这条不是必选)

补充(关于父子进程的理解):

其实我们到目前为止,不管是在命令行上所启动的进程,还是我们自己在代码层面上创建出来的进程,它都叫做子进程

Linux整个的进程结构本质就是一些父子关系的多叉树结构。那么我们命令行启动的所有的进程或者任务,最终其实都是父进程bash的子进程。想象一下,如果我们自己在fork的时候,虽然出现了父进程,但这个父进程它也是别人的子进程
 


系统怎么使用进程等待的?

代码验证:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>int main()
{pid id=fork();if(id<0){perror("fork");return 1;}else if(id==0){int cnt=5;while(cnt--){printf("I am child pid:%d,ppid:%d,cnt:%d \n",getpid(),getppid(),cnt);sleep(1);}exit(0);}else{//parentint cnt=10;while(cnt--){printf("I am child pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt);sleep(1);}pid_t ret=wait(NULL);if(ret==id){printf("wait success ,ret:%d\n")}sleep(5);}return 0;}

关于wait接口:

fork给我们对应的父子进程都会返回id值,子进程返回pid值等于0,
父进程的返回的pid其实这个就是子进程的pid。


wait:它就是用来让当前对应的父进程来进行等待子进程。
那么我们等待成功的时候ret是等待的子进程的pid。
换句话说,为什么要给父进程返回子进程的PID呢?
就是要用来判断我们当前父进程等待的时候等待的是哪个子进程,ret这个值返回值小于0小于0说明等待失败。

代码运行逻辑:

就是很显然这个程序一旦跑起来了:
那么对应的进程呢先创建父子进程
在前5秒的时候,父子都在运行,

5秒之后,子进程先退了之后变成僵尸状态等待回收
,但是我们的父进程依旧没有进行wait,因为它还在执行前面的while。

再过5秒之后,我们父进程回收子进程僵尸状态,最后父进程也结束;

所以进程等待是很有必要的!!!

如果我们有多个子进程需要回收,就需要创建多个wait来对其进行回收

如果子进程不退出,父进程默认在wait的时候,调用这个系统调用的时候,也就不返回,默认叫做阻塞状态!
 

关于waitpid接口:

pid_ t waitpid(pid_t pid, int *status, int options);

返回值:

当正常返回的时候waitpid返回收集到的子进程的进程ID;

如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;

如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;

参数:

pid:

Pid=-1,等待任一个子进程。与wait等效。

Pid>0.等待其进程ID与pid相等的子进程。

status:

WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)

WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)

options:

WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进 程的ID。

 
这里的waitpid参数这么写和wait的达到的效果是差不多的

关于status参数:
它是一个int*,也就是一个指针。但实际上呢,我们给它传参的时候确实是要传一个指针的。
只不过这里是为了通过wait或waitpid拿到指定进程或者任意一个进程它所对应的退出结果的。

第一个从语法角度,这个整数,它是一个输出型参数。

关于输出型参数:
关于输出型参数是c,c++语法的基础,就是期望通过对应的指针把函数内部所对应的数据带出来。
因为大家都知道我们传参一般都是要给函数传参的。
但有些形参最后我们可以把实际化之后变成指针。
然后通过status把函数内部的资源带出去,比如说对空间,比如说我们对应的返回值。
所以这种把值带出来的这种参数类型,我们叫做输出型参数
我的传参不是为了交给你对应的,这个函数什么,而是想让你函数交给我什么,这叫做输出型参数来。

第二,int看起来是整数,但是它这个int是被当做几部分使用的不要把这个int当做一个整数来看。

因为一个int在我们现有的这个平台当中
一个int类型占32比特位,那么也就意味着:我们其实是可以把我们所对应的这个int类型呢,可以看作成比如8个了、或者16个了。
所以把它分批可以表达不同的含义。
所以呢,这个int它是被当做几部分来使用的。
 



所以对我们来讲,我们想获取对应的结果呢。
在这里int就得定一个status变量这个变量名字可以随便起,只要它是个整数就行了。

一旦这个子定程它退出了。
我们会把它的退出信息拷贝到这个status指针所指向的变量当中。
所以当我们等待成功的时候,我们此时就能够得到这个子进程的对应退出信息。
 

 

其中这个status,它高16位不考虑,我们只考虑它的低16位
严格意义上讲是第8位,就是它的最低的。
那8个比特位用来表示的是我们这个当前进程是否出异常的问题

我们一个进程在异常终止时,一个子进程或者一个进程的异常时,本质是该进程收到信号了。

所以我们只要判断终止信号,这里的低7个比特位是否为0就能证明你的代码是否跑完
可是跑完就对吗?
不一定。

我们可以通过这里对应的次第8位:退出状态来得知子进程退出结果,所以就叫做退出状态。
所以退出状态为0,表示代码跑完结果正确,那么信号为0。
退出状态为1,代码跑完结果不正确,不正确的原因每一个不同的数字可以表示出错的不同原因。

父进程要拿子进程的状态数据或者任意数据,为什么必须要wait等系统调用呢?

首先父子进程之间是具有独立性的

所以你只能通过我们官方渠道----waitpid来指定进程获取它的特殊结果,并且父进程只能wait它对应的子进程。

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

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

相关文章

Webpack 性能优化 二次编译速度提升3倍!

本文作者为 360 奇舞团前端开发工程师 Rien. 本篇文章主要记录 webpack 的一次性能优化。 现状 随着业务复杂度的不断增加&#xff0c;项目也开始变得庞大&#xff0c;工程模块的体积也不断增加&#xff0c;webpack 编译的时间也会越来越久&#xff0c;我们现在的项目二次编译的…

评论:AlexNet和CaffeNet有何区别?

一、说明 在这个故事中&#xff0c;我们回顾了AlexNet和CaffeNet。AlexNet 是2012 年ILSVRC&#xff08;ImageNet 大规模视觉识别竞赛&#xff09;的获胜者&#xff0c;这是一项图像分类竞赛。而CaffeNet是AlexNet的单GPU版&#xff0c;因此&#xff0c;我们平时在普通电脑的Al…

Word或者WPS批量调整文中图片大小的快捷方法

文章目录 0、前言1、编写宏代码2、在文档中调用宏实现一键批量调整3、就这么简单&#xff01; 0、前言 不知道大家是不是也和我一样&#xff0c;经常需要在编写的Word&#xff08;或者WPS&#xff09;文档里插入大量的图片&#xff0c;但是这些图片的尺寸大小一般都不一样&…

PostgreSQL基本操作

目录 1.源码安装PostgreSQL 1.1.前置条件&#xff08;root下操作&#xff09; 1.1.1.卸载yum安装的postgresql 1.1.2.创建postgres用户 1.1.3.安装部分依赖 1.1.4.源码安装uuid 1.2.安装PostgreSQL 1.2.1.使用postgres用户管理PostgreSQL 1.2.2.下载解压postgres12源码…

Git | Git的基本操作以及原理介绍

文章目录 基本操作创建git仓库配置name和email .git目录的结构git add & git commit.git目录结构的变化 git追踪管理的数据git的版本回退回退的原理回退的三种情况 版本库中文件的删除git分支管理分支的删除合并分支时的冲突分支的合并模式分支策略git stash不要在master分…

大文件分片上传、断点续传、秒传

小文件上传 后端&#xff1a;SpringBootJDK17 前端&#xff1a;JavaScriptsparkmd5.min.js 一、依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.2</ve…

(论文阅读30/100)Convolutional Pose Machines

30.文献阅读笔记CPMs 简介 题目 Convolutional Pose Machines 作者 Shih-En Wei, Varun Ramakrishna, Takeo Kanade, and Yaser Sheikh, CVPR, 2016. 原文链接 https://arxiv.org/pdf/1602.00134.pdf 关键词 Convolutional Pose Machines&#xff08;CPMs&#xff09;…

asp.net core weapi 结合identity完成登录/注册/角色/权限分配

1.安装所需要的nuget包 <PackageReference Include"Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version"6.0.24" /><PackageReference Include"Microsoft.EntityFrameworkCore" Version"6.0.24" /><PackageR…

windows系统pycharm程序通过urllib下载权重https报错解决

报错内容&#xff1a; raise URLError(unknown url type: %s % type) urllib.error.URLError: <urlopen error unknown url type: https> 解决办法记录&#xff1a; 1. 下载 pyopenssl : pip install pyopenssl 此时&#xff0c; import ssl 可以通过提示指导你安…

redis基线检查

1、禁止使用 root 用户启动 | 访问控制 描述: 使用root权限来运行网络服务存在较大的风险。Nginx和Apache都有独立的work用户,而Redis没有。例如,Redis的Crackit漏洞就是利用root用户权限替换或增加authorize_keys,从而获取root登录权限。 加固建议: 使用root切换到re…

SpringBoot项目集成发邮件功能

1&#xff1a;引入依赖2&#xff1a;配置设置3&#xff1a;授权码获取&#xff1a;4&#xff1a;核心代码5&#xff1a;postman模拟验证6&#xff1a;安全注意 1&#xff1a;引入依赖 <dependency><groupId>org.apache.commons</groupId><artifactId>c…

【星海出品】SDN neutron (四) 流分析

Neutron框架之流分析 1.控制端neutron-server通过wsgi接收北向REST API请求&#xff0c;neutron-plugin通过rpc与设备端进行南向通信。 2.设备端agent则向上通过rpc与控制端进行通信&#xff0c;向下则直接在本地对网络设备进行配置。 3.Neutron-agent的实现很多&#xff0c;彼…