【Linux】-进程概念及进程状态(僵尸进程和孤儿进程)

news2024/11/15 10:25:47

在这里插入图片描述
💖作者:小树苗渴望变成参天大树🎈
🎉作者宣言:认真写好每一篇博客💤
🎊作者gitee:gitee✨
💞作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法🎄
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 一、初步认识三种状态:
    • 1.1运行态
    • 1.2阻塞态
    • 1.3挂起态
  • 二、Linux上的状态
    • 2.1R状态
    • 2.2S状态
    • 2.3D状态
    • 2.4T和t状态
    • 2.5Z和X状态
  • 三、总结


前言

上篇我们刚刚讲解完毕task_struct里面的第一个内容标识符,也讲解了fork的具体作用和用途,今天这篇我在带大家来学习task_struct里面另一个属性-进程状态,这个也是非常重要的,由于内容比较多,所以我选择单独一篇博客给大家介绍,希望大家可以更好的理解,此篇主要是概念,所以文字相对较多,代码相对较少,也希望各位读者可以耐心的阅读下去,话不多说,我们开始进入正文


task_ struct内容分类

标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。
程序计数器: 程序中即将被执行的下一条指令的地址。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据: 进程执行时处理器的寄存器中的数据。
I/O状态信息: 包括显示的I/O请求分配给进程的I/O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
其他信息

一、初步认识三种状态:

我们先从一般的操作系统学科来介绍三种常见的状态:运行,阻塞,挂起
还有其他状态都不是特别的重要,然后我们再来学习Linux上的状态是什么样的,我们在网上找一些操作系统状态图
在这里插入图片描述

相信大家对这些名词几乎不了解,可能也没有听说过,接下来我就给大家进行解释

1.1运行态

在这里插入图片描述

通过这个图相信大家已经理解了什么是运行态了吧

1.2阻塞态

这个状态不太好理解,还是需要画图来能给大家去介绍的
在这里插入图片描述

阻塞态是进程和外设之间的资源请求,通过外设输入数据让进程可以继续运行下去,相信大家应该了解了进程的阻塞态了吧

1.3挂起态

挂起态可以说是在阻塞态的基础上产生的状态
在这里插入图片描述

相信大家此时对挂起态有了一定的了解了

通过上面的三种进程的状态的了解,我们来看看Linux上是怎么处理他上面进程的状态

二、Linux上的状态

在这里插入图片描述
我们有这么多状态,博主都会一一介绍的,大家不用担心。

2.1R状态

Linux的R状态就是运行状态和我上面介绍的运行态是一样的道理,在运行队列里面就是运行态
我们来看一段代码:

#include<stdio.h>
int main()
{
    while(1)
    {
        printf("我是一个进程\n");
    }
    return 0;
}

#include<stdio.h>
int main()
{
    while(1);
    return 0;
}

在这里插入图片描述

第一个程序和第二个程序都是写了一个死循环,而且都是没有在终止进程的时候去查看的,为什么第一个程序是S状态,而第二个程序是R状态首先S状态先理解为阻塞状态,我们的cpu运行太快了,因为第一个程序是一个死循环,所以肯定不止在cpu上就跑一次,他应该一直从cpu被拿下被放上,在运行队列里面待着,但是他每次放下来需要去打印,由于打印是和外设打交道,而外设太慢了,所以不能一直放在运行队列中等待排队,万一又到我这个程序开始运行了,但我还在往外设的显示器是慢慢打印呢,这时候是不是就没有准备好,所以就不能放在运行队列上,此时应该在等待队列上等待打印,等打印好了,又会被放到运行队列,在跑下一次,由于速度都很快,我们观察到的结果就是一直在运行的状态给我们一定的错觉,大部分时间都在等待队列待着等待打印,所以我们大概率看到都是S状态那第二个程序呢?他由于没有与外设打交道,所以他是一直在运行队列,不停的拿上拿下,但始终在运行队列中,所以看到就是R状态

我们看到状态后面的+号是什么?
他标识前台运行,意味我们其他程序跑不了,因为他一直在运行,我们命令都输入不了,我们可以在运行的时候加一个&让他变成后台运行./myproc &
在这里插入图片描述
此时就是后台运行,由于后台运行没有办法使用CTRL+c结束程序,所以我们必须使用这个命令把程序杀死kill -9 PID,-9是一个信号,一会还会介绍到其他两个信号。
在这里插入图片描述
相信大家对Linux上的R状态(运行状态)应该有所了解了吧

2.2S状态

我们在R状态提到过,S状态,我们可以暂时理解为阻塞态,在Linux上我们理解为睡眠状态:意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。可中断请求就是可以随时被唤醒,介绍R状态的时候我们往显示器去打印,就是等待打印任务完成,当正在打印的时候,就是睡眠状态,打印好了就被唤醒了。

我们来看案例:

#include<stdio.h>
int main()
{
     int n=0;
     scanf("%d",&n);                             
     return 0;
}

在这里插入图片描述

我们等待键盘输入的时候就是在等待事件的完成,所以是处于S状态.


我们在来看看我们的bash程序:
在这里插入图片描述

大小S不用管都是属于睡眠状态,我们的bash就是命令行解释器,等待我们输入命令,就是等待事件的完成,所以也是阻塞态,只要是和外设有交流的进程都可以理解为睡眠状态(只包括浅度睡眠),不止是键盘和显示器。

我们大部分看到的进程都是处于阻塞态,为了显示效果,写特殊的代码让大家看到其他状态。相信到这个时候大家对Linux上的S状态(浅度睡眠状态)应该了解了吧。

2.3D状态

这个状态和睡眠状态很像,上面叫浅度睡眠,可以随时被唤醒,而D状态他叫深度睡眠,不可中断的睡眠状态,不会相应任何人的命令,这个状态不太好展示的,有可能造成数据丢失,所以我将会以一个小故事的形式来给大家进行展示:

小故事时间:

D状态也叫睡眠状态,他的操作是等待IO时间完成,这时候我们的进程假设要将1GB的数据放到磁盘里面,磁盘跟进程说,你这个1GB数据不一定能放的下,放不放的下我到时候到来跟你说一声,万一放不下去,我在把已经放下数据在还给你,你先等我一下,我速度很慢的,此时的进程就翘着二郎腿在等啊等啊,此时操作系统路过了,他正在清理占用资源的进程,此时发现这个进程有没有在使用,说你等啥等呢,浪费我内存的资源,直接给这个进程清理掉了,此时硬盘放着放着发现放不下,就不好意思的回来告诉进程,可进程去不见了,硬盘就不知道怎么办了,硬盘心想我不知道还给谁啊,但别的进程还有放数据进来啊,不能占用资源啊,直接给丢掉了,万一这是一个非常重要的银行转账记录,那损失可就大了。


此时就来了一法官,他要追究到底是谁的责任啊
操作系统辩论:法官大人,这可不能怪我啊,我们的本质工作就是维护进程,管理内存空间,他占用内存资源,导致内存严重不足,数据丢失和我没有关系,我只管合理分配内存空间给进程使用,如果不清理他,导致其他进程崩溃,那样损失更大,该丢的数据还是得丢失
磁盘辩论:法官大人,这事和我也没有关系,我放的时候就已经和进程说了可能放不进去,让进程等待我一下,我就是一个打工人,别人说什么就是什么可最后他人却不见了,我也不知道把数据放在哪里,其他进程还要放数据呢?不能耽误别人,我没有办法只有丢掉
进程辩论: 法官大人,我才是受害者啊,我在等待磁盘给我回复的过程中,操作系统直接来二话不说给我带走了,这不是自己的行为,我i也没办法啊


法官大人听了三个人的辩词说的都有道理,也不知道判定是谁的问题了,好心的法官就自己承担了此次损失,好在法官是程序员,进程和磁盘工作好好的,是操作系统路过把两人直接的交流打断的,索性法官直接修改操作系统,给此进程一个免死金牌,任何响应都不能影响此进程和磁盘直接的交流,操作系统也不行,所以此时的进程就处于深度睡眠状态,没有人可以中断他,也叫D状态

现在都是固态硬盘速度也是比较快的了,所以进程不需要怎么等待硬盘的回复,所以也很少出现D状态,偶尔出现一个就不得了,出现多了那么你的操作系统肯定就会挂掉。所以D状态我们知道是什么就行了,我就不给大家验证了,博主怕自己的linux操作系统崩溃掉😂,相信到这里大家对D状态(深度睡眠状态)已经有所理解了吧

2.4T和t状态

这两个目前没有啥区别,我们当成一个状态就行了

T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
我们来看案例:

 #include<stdio.h>  
 int main()  
 {
       while(1)
       {
           printf("我一会就要停止运行啦\n");       
       }  
       return 0;
  }  

在这里插入图片描述
9号信号我们刚才已经使用过了,是杀掉进程的,19号信号是停止程序,18号信号是恢复程序。

停止: kill -19 PID
在这里插入图片描述
恢复: kill -18 PID
在这里插入图片描述
我们看到我们恢复之后就默认变成后台运行,为啥看到是S这里我就不多说了。


我们最常见停止程序是什么??gdb 他不打断点r是直接运行结束,打了断点会在断点处停止,我们需要将我们的程序加-g选项,才能调试
我们来看测试:
在这里插入图片描述

所以我们的断点里面肯定也有一些关于停止信号的命令,导致程序可以被暂停。相信到这里大家对停止状态已经有所了解了吧

2.5Z和X状态

这两个状态是有一个先后关系的,先是X状态然后到X状态,先来介绍一下神叫做Z状态

Z(zombie)-僵尸进程:

  1. 僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
  2. 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
  3. 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

大家肯定不理解,此时又到 小故事时间

有一天你悠闲的在路上小跑,突然有一个人飞速的跑过去,然后在你前方两百米的地方突然躺平了,你跑过去处于好心,拨打了119和110,此时119快速的来到了现场,然后发现这俄格人救不活了,然后就撤了,此时110来了,他第一件事情不是直接清理现场,而是要保护现场,找法医来看看死者的死因是什么,然后拉起禁戒线,等待家属来,这段时间这个人会一直在这躺着。此时就好比进程一直处于僵尸状态。


那么到底谁最关心你的死活,是不是就是家属,在Linux中就是父进程,他最关系你了,他需要把你的尸体清理带走,在Linux中,父进程就要清理子进程退出后的代码,如果父进程一个不清理读取的话,那么此时的子进程就一直会在哪没人清理,处于僵尸状态。

所以这个时间大家对僵尸进程是不是有所了解了,就是子进程推出后,父进程一直不读取他的退出码,他就一直清理不掉,处于僵死状态,所以我们需要使用fork来创建父子进程,来测试我们想要的效果:

  1 #include<stdio.h>                                                                  
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 #include<stdlib.h>
  5 int main()
  6 {
  7     pid_t id=fork();
  8     if(id==0)
  9     {
 10         int cnt=5;
 11         while(cnt)
 12         {
 13             printf("我是子进程,pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt--);
 14             sleep(1);
 15         }
 16         exit(0);//主动让进程退出,而不是程序退出了他在退出,模拟父进程在运行没有时间清理父进程
 17     }
 18     else if(id>0)
 19     {
 20 
 21         while(1)
 22         {
 23             printf("我是父进程:pid:%d,ppid:%d\n",getpid(),getppid());
 24             sleep(1);
 25 
 26         }
 27     }
 28     return 0;
 29 }

使用此命令监视进程状态:while :; do ps axj | head -1 && ps axj | grep myproc | grep -v grep ; sleep 1 ; done

在这里插入图片描述
我们发现子进程退出之后父进程在忙着运行自己的程序还没有读取到子进程的退出码,所以子进程一直是处于僵尸状态,这个单词defunct这就是死的意思。

显然僵尸进程是不好的,所以来说说僵尸进程有哪些危害:

  1. 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!
  2. 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护?是的!
  3. 那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!
  4. 内存泄漏?是的!
  5. 如何避免,后面介绍

说完Z进程,我们来看看X进程:这个状态只是一个返回状态,你不会在任务列表里看到这个状态,他是一个瞬时的状态。


接下来我们再来介绍一下另一个进程-孤儿进程
上面的僵尸进程是子进程先退出,父进程没有及时去清理,而孤儿进程是反的,父进程退出了,子进程到最后没人清理,就变成孤儿了,遇到这种情况,我们看看操作系统是怎么处理的

  1#include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 #include<stdlib.h>
  5 int main()
  6 {
  7     pid_t id=fork();
  8     if(id>0)
  9     {
 10         int cnt=5;
 11         while(cnt)
 12         {
 13             printf("我是父进程,pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt--);
 14             sleep(1);
 15         }
 16         
 17         exit(0);
 18     }
 19     else if(id==0)
 20     {
 21 
 22         int cnt=15;
 23         while(cnt)
 24         {
 25             printf("我是子进程:pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt--); 
 26             sleep(1);
 27         }
 28 
 29     }
 30     return 0;
 31 }

在这里插入图片描述
通过上面的示例我们发现,我们的父进程退出之后,我们的子进程的父进程就变成1,我们来看看PID是1的进程是哪个程序:
在这里插入图片描述
这个1号进程正是我们的操作系统的进程,我们的操作系统领养了我们的子进程,
为什么要领养呢?为了方便子进程退出,有人给他清理资源
为什么bash补领养呢?因为bash只负责自己的子进程,没有能力领养。
相信此时大家对孤儿进程应该了解了吧

至此,值得关注的进程状态全部讲解完成

三、总结

到这里我们关于Linux上的进程都讲解完毕了,不知道同学们有没有收获,概念性比较多,但理解了就简单了,博主使用生动的小故事就是为了让大家可以更好的理解进程状态,希望大家可以可以都偶都支持博主,下篇我们开始介绍进程的优先级,也是一个非常关键的属性,希望大家到时候来支持博主,我们下篇再见

请添加图片描述

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

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

相关文章

基于中文金融知识的 LLaMA 系微调模型的智能问答系统:LLaMA大模型训练微调推理等详细教学

项目设计集合&#xff08;人工智能方向&#xff09;&#xff1a;助力新人快速实战掌握技能、自主完成项目设计升级&#xff0c;提升自身的硬实力&#xff08;不仅限NLP、知识图谱、计算机视觉等领域&#xff09;&#xff1a;汇总有意义的项目设计集合&#xff0c;助力新人快速实…

x86架构ubuntu22下运行WILL模拟器dophin

0. 环境 i5实体机ubuntu22 1. 安装依赖 $ sudo apt install build-essential git cmake ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libevdev-dev libusb-1.0-0-dev libxrandr-dev libxi-dev libpangocairo-1.0-0 qt6-base-private-dev libblueto…

MybatisPlusInterceptor实现sql拦截器(超详细)

1 . 导入pom <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency> 2 . 配置下MybatisPlus的yml mybatis-plus:mapper-locations:- …

ssm学生贷款管理系统java助学贷银行jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 ssm学生贷款管理系统 系统有1权限&#xff1a;管理员…

自己搭建一个KMS服务器

本文仅适合个人用户&#xff0c;商业用户使用该程序可能会面临法律风险&#xff01;&#xff01;&#xff01; 建议有经济能力的读者支持正版。 知周所众&#xff0c;Windows和Office不是免费软件。如果是新购买的品牌机&#xff0c;则应该预装有正版的Windows家庭版&#xf…

Java+bcprov库实现对称和非对称加密算法

BouncyCastle&#xff0c;即BC&#xff0c;其是一款开源的密码包&#xff0c;包含了大量的密码算法。 本篇主要演示BC库引入&#xff0c;对称加密算法AES、SM4和 非对称加密EC算法的简单实现&#xff0c;以下是实现过程。 一、将BC添加到JRE环境 前提&#xff1a;已安装JRE环…

jmeter实现webservice接口测试

其实可以用jmeter两种sampler进行webservice的测试&#xff1a; 1、SOAP/XML-RPC Request(但是在jmeter3.2以后版本中已经取消了这个取样器) 2、HTTP请求 下面分别介绍两种方式 一、首先需要使用soupUI工具抓取webservice接口的部分需要的信息。 1、新建项目 2、新建成功的…

jenkins部署springboot项目(超详细讲解)

原来写了一篇博客是如何安装jenkins的&#xff0c;今天也来介绍一下怎么简单使用吧。 首先&#xff0c;我们要明确&#xff0c;jenkins自动化部署也只是代替你去做你要做的事&#xff0c; 我们梳理一下&#xff0c;你的代码写完&#xff0c;打包&#xff0c;扔到服务器上&…

tcp三次握手python实现和结果

下载抓包工具 安装 使用1 使用2 结果 红色笔为想要发送的数据。 代码 from scapy.all import * import logginglogging.getLogger(scapy.runtime).setLevel(logging.ERROR)target_ip = 172.20.211.4 target_port = 80 data = GET / HTTP/1.0 \r\n\r\ndef start_tcp(target_…

火爆全网,Charles抓包教程-辅助接口测试(二)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 功能图标 从左到右…

mysql综合练习语法总结

mysql综合练习 用于 小白练手的主要用于以后语法忘了回来看 题目 # 1、创建数据库test01_library # 2、创建表 books&#xff0c;表结构如下&#xff1a;# 3、向books表中插入记录 # 1&#xff09;不指定字段名称&#xff0c;插入第一条记录 # 2&#xff09;指定所有字段名…

经典的数组和指针结合的OJ题

一、合并两个有序数组 leetcode链接 题目描述&#xff1a; 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递…

seata组件使用期间,获取全局事务状态

GlobalStatus枚举类展示全局事务状态 官网链接&#xff1a;http://seata.io/zh-cn/docs/user/appendix/global-transaction-status.html 获得全局事务状态 // 开启全局事务地方获取全局事务xid String xid RootContext.getXID(); // 通过全局事务xid获得GlobalStatus枚举类 …

Transformer 论文学习笔记

重新学习了一下&#xff0c;整理了一下笔记 论文&#xff1a;《Attention Is All You Need》 代码&#xff1a;http://nlp.seas.harvard.edu/annotated-transformer/ 地址&#xff1a;https://arxiv.org/abs/1706.03762v5 翻译&#xff1a;Transformer论文翻译 特点&#xff1…

【Qt】利用Tool Button控件创建下拉菜单按钮

功能描述 利用qt进行界面设计和开发&#xff0c;创建下拉按钮。 详细实现 1、在qt侧工具栏利用设计打开.ui文件 2、创建按钮 创建一个Tool Button按钮&#xff0c;并在属性窗口中的QToolButton栏中选中MenuButtonPopup属性。 3、创建action 在Action编辑器创建对应的ac…

Dual pyramid GAN for semantic image synthesis

为了解决在图像合成时候小物体容易消失&#xff0c;大物体经常作为块的拼接来生成的。本文提出DP-GAN在所有尺度下共同学习空间自适应归一化模块的条件。这样尺度信息就会被双向使用&#xff0c;他统一了不同尺度的监督。(重点看图和代码) SPADE模块解释 GAN在生成包含许多不同…

JavaScript学习 -- 对称加密算法DES

在现代的互联网时代&#xff0c;数据安全性备受关注。为了保护敏感数据的机密性&#xff0c;对称加密算法是一种常用的方法。在JavaScript中&#xff0c;DES&#xff08;Data Encryption Standard&#xff09;是一种常用的对称加密算法。本篇博客将为您展示如何在JavaScript中使…

npm i 报错项目启动不了解决方法

1.场景 在另一台电脑低版本node环境跑的react项目&#xff0c;换到另一台电脑node18环境执行npm i时候报错 2.解决方法 脚本前加上set NODE_OPTIONS--openssl-legacy-provider

使用稀疏性(微球)进行色谱图基线估计和去噪(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

okvis

论文 Keyframe-Based Visual-Inertial SLAM Using Nonlinear Optimization 摘要 由于两种感知模式的互补性&#xff0c;视觉和惯性线索的融合在机器人中变得很流行。虽然迄今为止大多数融合策略都依赖于过滤方案&#xff0c;但视觉机器人界最近转向了非线性优化方法&#x…