【Linux】僵尸与孤儿 进程等待

目录

一,僵尸进程

1,僵尸进程

2,僵尸进程的危害

二,孤儿进程

1,孤儿进程

三,进程等待

1,进程等待的必要性

2,wait 方法

3,waitpid 方法

4,回收小结


一,僵尸进程

1,僵尸进程

僵死状态(Zombies)是一个比较特殊的状态。

当进程退出并且父进程(使用wait()系统调用,后面讲) 没有读取到子进程退出的返回代码时就会产生僵死(尸)进程 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

来一个创建维持30秒的僵死进程例子:

#include <stdio.h>
#include <stdlib.h>
int main()
{pid_t id = fork();if (id < 0) {perror("fork");return 1;}else if (id > 0) { //parentprintf("parent[%d] is sleeping...\n", getpid());sleep(30);}else {printf("child[%d] is begin Z...\n", getpid());sleep(5);exit(EXIT_SUCCESS);}return 0;
}

当fork()函数返回值,父进程和子进程同时启动,当子进程运行结束退出进程时,父进程还在等待,此时子进程一直在等待父进程读取其退出状态代码,于是产生了僵尸状态;

僵尸状体会造成内存泄漏,我们要尽可能避免;

2,僵尸进程的危害

进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!

维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护?是的!

那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!

内存泄漏?是的!

二,孤儿进程

1,孤儿进程

父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?

父进程先退出,子进程就称之为“孤儿进程”

孤儿进程被1号init进程领养,当然要有init进程回收喽。

我们写一个进程来感受一下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{pid_t id = fork();if (id < 0) {perror("fork");return 1;}else if (id == 0) {//childprintf("I am child, pid : %d\n", getpid());sleep(10);}else {//parentprintf("I am parent, pid: %d\n", getpid());sleep(3);exit(0);}return 0;
}

fork()函数返回后,子进程和父进程同时运行,当父进程执行结束并且退出后,子进程还在运行,此时子进程沦为孤儿!

一般孤儿进程最后会被1号init进程领养,不会造成内存泄漏;

三,进程等待

1,进程等待的必要性

之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。

另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。

最后,父进程派给子进程的任务完成的如何,我们需要知道。如子进程运行完成,结果对还是不对, 或者是否正常退出。

父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

2,wait 方法

pid_t wait(int*status);

返回值: 成功返回被等待进程pid,失败返回-1。

参数: 输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

#include <stdio. h>
#include <unistd.h>
#include <stdlib.h>
#include<sys/types.h>
#include<sys / wait.h>
int main()
{pid_t id = fork();if (id < 0) {perror("fork");return 1;}else if (id == 0) {//parentprintf("child[%d] is sleeping...\n", getpid());sleep(5);exit(3);}int status = 0;pid_t rid = wait(&status);if (rid > 0){printf("parent[%d] is begin Z...\n", rid);sleep(10);}else {printf("进程失败:rid:%d\n", rid);}return 0;}

这样子 wait 会自动及时回收子进程,不会形成僵尸,不会造成内存泄漏;

3,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。

#include <stdio. h>
#include <unistd.h>
#include <stdlib.h>
#include<sys/types.h>
#include<sys / wait.h>
int main()
{pid_t id = fork();if (id < 0) {perror("fork");return 1;}else if (id == 0) {//parentprintf("child[%d] is sleeping...\n", getpid());sleep(5);exit(3);}int status = 0;pid_ t rid = waitpid(-1,&status,0);if (rid > 0){printf("parent[%d] is begin Z...\n", rid);sleep(10);}else {printf("进程失败:rid:%d\n", rid);}return 0;}

4,回收小结

如果子进程已经退出,调用wait/waitpid时,wait/waitpid 会立即返回,并且释放资源,获得子进程退出信息。

如果在任意时刻调用 wait/waitpid,子进程存在且正常运行,则进程可能阻塞。

如果不存在该子进程,则立即出错返回。

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

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

相关文章

vue场景 无分页列表条件过滤,子组件多选来自父组件的列表

日常开发中&#xff0c;经常会遇到下面场景&#xff1a; 页面加载一个无分页列表&#xff0c;同时工具栏设置多个条件可对列表过滤的场景(典型的就是关键字模糊查询)父组件传给子组件列表&#xff0c;子组件中需要多选列表多选&#xff0c;选择结果返回父组件 1 无分页列表过…

Tg5032smn:高稳定性105℃高温

TG5032SMN是一款频率范围10MHz ~ 54MHz,具有高稳定的TCXO晶振&#xff0c;可与CMOS或限幅正弦输出。外部尺寸5.0 3.2 1.45mm&#xff0c;超小型,质地轻。该系列晶振的额定工作范围-40℃~&#xfe62;105C内可高稳定性工作&#xff0c;使得信号频率的误差很小。TG5032SMN与其他…

Android Termux安装SSH结合内网穿透实现远程SFTP文件传输

文章目录 1. 安装openSSH2. 安装cpolar3. 远程SFTP连接配置4. 远程SFTP访问4. 配置固定远程连接地址 SFTP&#xff08;SSH File Transfer Protocol&#xff09;是一种基于SSH&#xff08;Secure Shell&#xff09;安全协议的文件传输协议。与FTP协议相比&#xff0c;SFTP使用了…

Linux的安装及管理程序

一、如何在linux安装卸载软件 1. 编译安装 灵活性较高 难度较大 可以安装较新的版本 2. rpm安装&#xff08;redhat&#xff09; linux 包安装 查软件信息&#xff1a;是否安装&#xff0c;文件列表 rpm 软件名 3. yum yum是RPM升级版本&#xff0c;解决rpm的弊端 安装软件 首…

9.独立看门狗IWDG窗口看门狗WWDG编码思路

前言&#xff1a; 看门狗是维护系统稳定性的一向技术&#xff0c;可以让代码跑飞及时复位&#xff0c;在产品中非常常用&#xff0c;俗话说&#xff0c;重启能解决90%的问题&#xff0c;作为产品来说&#xff0c;你总不能因为一次bug就让程序卡死不动了&#xff0c;肯定要试着重…

WEB 3D技术 three.js 集合体 讲解三角形构建图形 顶点概念 顶点值重用

那么 本文 我们来说一下集合体 我们要创建物体 都要先创建一个集合体 集合体也决定了我们元素的形态 材质 决定了我们的外观 我们结合体 其实基础都是三角形 我们编写如下代码 import ./style.css import * as THREE from "three"; import { OrbitControls } from …

截断整型提升算数转换

文章目录 &#x1f680;前言&#x1f680;截断&#x1f680;整型提升✈️整型提升是怎样的 &#x1f680;算术转换 &#x1f680;前言 大家好啊&#xff01;这里阿辉补一下前面操作符遗漏的地方——截断、整型提升和算数转换 看这一篇要先会前面阿辉讲的数据的存储否则可能看不…

绑定Open AI api-key获取token要怎么操作?

要绑定OpenAI的付费计划并获取API key来调用token接口&#xff0c;你需要按照以下步骤操作&#xff1a; 1. 访问OpenAI官网&#xff1a; 打开浏览器&#xff0c;输入 https://openai.com/&#xff0c;并访问OpenAI的官方网站。 2. 注册/登录账户&#xff1a; 如果你还没有Ope…

揭秘亚马逊中国站API接口:挖掘无限商机,实现高效数据获取

一、概述 亚马逊中国站API接口是一种应用程序接口&#xff0c;允许开发者通过编程方式访问亚马逊中国站的数据和服务。通过使用API接口&#xff0c;开发者可以轻松地获取商品信息、用户数据、订单状态等&#xff0c;从而为他们的应用程序或网站提供更加丰富的内容和功能。 二…

T-Dongle-S3开发笔记——相关配置

portTICK_PERIOD_MS设置 Flash配置 Flash SPI mode 默认是DIO&#xff0c;改为QIO (W25Q128支持QIO) DIO与QIO区别&#xff1a; esp8266&#xff0c;esp32中的SPI FLASH 访问模式&#xff08;QIO QOUT DIO DOUT&#xff09;_qio dio-CSDN博客 Dual SPI:MOSI 和 MISO 引脚…

Spring Boot Security认证:Redis缓存用户信息

文章目录 1. 引言2. Spring Boot Security简介3. 集成Spring Boot Security4. 配置Spring Boot Security5. Redis配置6. Redis缓存用户信息7. 使用Redis缓存的用户信息进行认证8. 测试认证功能9. 性能优化与拓展9.1 性能优化9.2 拓展功能 10. 总结 &#x1f389;欢迎来到架构设…

Gradle下载地址

Gradle下载地址 Gradle是一个基于JVM的构建工具&#xff0c;是一款通用灵活的构建工具&#xff0c;Gradle也是第一个构建集成工具&#xff0c;与ant、maven、ivy有良好的相容相关性。支持maven&#xff0c; Ivy仓库&#xff0c;支持传递性依赖管理&#xff0c;而不需要远程仓库…