进程状态(三)----- linux 中具体的进程状态(下)

news2024/9/27 0:58:08

目录

  • 前言
  • 1. T && t 状态
  • 2. X 与 Z 状态
  • 3. 孤儿进程

前言

继上一篇文章 进程状态(二)----- linux 中具体的进程状态(上) 介绍了 linux 系统中具体的 R、S、D 状态,而这篇文章继续介绍 linux 系统中剩下的三种状态,T && t 状态,X 与 Z 状态,以及孤儿进程的由来。

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

1. T && t 状态

T 和 t 状态,我们放在一块讲,因为在如今的 linux 系统中,这两个基本已经没有什么区别了。所谓 T 状态,就是 stop,就是让进程停下来。

当我们进程跑起来的时候,我们可以通过如下指令,将进程暂停一下。

[outlier@localhost process2]$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

其中的 19 信号就是将进程暂停,18 信号恢复进程(恢复之后的进程会变为后台进程,需要通过 kill 指令杀掉进程才能够关闭)

在这里插入图片描述

大家会不会有一个疑问就是,一个进程处于暂停状态 和 一个进程处于 sleep 状态,有什么区别吗?在最直观的理解上,这两种进程都是不被 cpu 执行的进程。所以为什么进程要暂停下来呢?它是不是也像 sleep 一样,在等待某种资源的就绪呢?

面对这类问题,我们可以这样去解读,有时候我们就是想要暂停一下这个进程,等待其它事件的发生,而非等待某种资源的就绪,我们可以将其设置为 T 状态,而 T 状态下,进程的代码就完全暂停了,一般而言也不接受其它信号了,并且 T 状态在某种程度上也算是一种阻塞状态。与 sleep 不同的是,sleep 一定是在等待某种资源,但是 stop 状态不一定是在等待资源,也可以是人为控制下的暂停。

那么为什么我们要暂停一个进程呢? ---- gdb 调试的时候,是不是就是 gdb 帮助我们暂停进程的?

在这里插入图片描述

借助 gdb,进程运行到断点处停下来了,此时的进程状态从 sleep 变为了 stop(只不过是 小 t 的暂停状态)。所以凭什么你运行到断点处,你的代码就很乖的停下来了,这一切不都是 gdb 这个调试工具帮你做的吗,而这种场景就是暂停进程的应用场景之一。、

2. X 与 Z 状态

X(dead) 状态,字面意思直接拿捏,它就是死亡状态!一个进程处于死亡状态,是什么含义?不就是这个进程因为各种原因然后停止运行了,而这个状态只是一个返回状态,也无法在任务列表里看到这个状态。

但是进程在进入 dead 状态之前,背后可是存在着一系列的事情,简单说,那就是,进程因为某种原因挂掉了,它并不会马上进入 X 状态,而是先进入 Z 状态,即僵尸状态。

那么背后是怎么一个事呢?讲个故事。

有一天早晨,张三和往日一样进行着晨跑。途中,有一个看起来较为专业的哥们,从张三的身边一闪而过,张三一开始也没多想,还是按照自己的节奏跑着。不久后,张三突然发现前面有个人 “躺平” 了,正好是刚刚一闪而过那哥们。张三哪见过如此场面,直接先后拨打了120,110。等待救护车来临之后,做了急救措施,最终宣判那哥们 dead 了,而此时帽子叔叔也已经赶到。所以既然现在人也已经彻底躺平了,于是救护人员也就离开。此刻,这个哥们已经彻底躺平是事实,但是帽子叔叔并没有宣布其躺平的消息,也没有立刻通知哥们的家属对其进行回收,而是叫了两法医对那哥们进行鉴定(判断是自杀?ta 杀?意外躺平?),毕竟好端端的一个人,突然在大庭广众之下彻底躺平,总得给社会一个交代吧?直到法医鉴定完毕,确定那哥们的躺平原因之后,帽子叔叔才正式通知其家属来认领并回收那哥们。

而在张三看到那哥们躺平开始,一直到法医鉴定躺平原因这段期间内,那哥们就一直需要在那躺平着,此时这个人的状态就称为 僵尸状态!当帽子叔叔那边鉴定完这哥们躺平的原因之后,准备通知家属进入到回收阶段了,那么这个人的状态就称为死亡状态。

所以进程也如此,一个进程退出了,并不是立刻进入 dead 状态,而是操作系统会将该进程的退出信息维持一段时间,以让关心这件事的主体得知该进程退出的原因等信息。所以对一个已经退出的进程,操作系统在维护其退出信息的这段时间内,这个进程的各种资源还没有得到释放的,我们就把这种进程称为 僵尸进程!

而一个进程退出之后,那么最关心这个进程的肯定是他的父进程。假设今天有一对父子进程,子进程退出了,但是它的父进程迟迟没有来 “关心” 它,自顾自的运行着,那么操作系统就必须把子进程的状态一直维持着,直到父进程前来回收子进程。所以再次强调,我们把这种已经死掉的进程,但是又需要有父进程前来回收的这种进程的状态,称为Z 状态,即僵尸状态。 到这里,讲了这么多,那总得见一见僵尸进程吧?

int main()
{
    pid_t pid = fork();
    if(pid == 0)
    {
     	// 子进程
        int cnt = 5;
        while(cnt)
        {
            cout << "I am a child process, pid: " << getpid() << ", ppid: " << getppid() << ", cnt: " << cnt << endl;
            cnt--;
            sleep(1);
        }
		exit(0);
    }
    else
    {
     	// 父进程
        while(1)
        {
            cout << "I am a parent process, pid: " << getpid() << ", ppid: " << getppid() << endl;
            sleep(1);
        }
    }
}

在这里插入图片描述

在这次测试中,我们先退出了子进程,而在退出前,父子进程绝大部分时间都处于 sleep 状态,当子进程退出后,由于父进程并没有对子进程进行回收,因此子进程所呈现出来的状态并不是 dead 状态,而是 zombie 僵尸状态。

所以一个进程退出之后,没有及时被其父进程主动回收,这个进程资源就会一直被维持在内存当中,而这种进程既然已经变成 Z 状态了,那么它就一定不会被操作系统调度了,更不会被运行。所以这种问题就会导致 内存泄漏!而为什么在我们关闭我们的 test 进程之后,其创建出来的子进程变为 Z 状态(这现在我可以理解,因为父进程没有主动回收),那为什么其父进程却并没有呈现 Z 状态呢?而是直接退出了,难道是父进程的父进程对其进行了回收吗?

3. 孤儿进程

没错,在运行 test 这个程序之后,bash 这个进程会自动为 test 创建出进程,而 bash 作为 test 的父进程,当 test 这个进程退出时,bash 就有对它进行回收的义务!而事实就是如此,子进程是 test 这个进程创建出来的,但当子进程退出时,由于父进程并没有对其进行关心,因此该子进程的退出信息就要一直被维护下去(退出信息也是数据,保存在 task_sturct 中,也相当于在维护 PCB)。

那相反过来呢?如果是父进程退出了,子进程还在继续运行会是怎么样的现象?父进程提前退出,那子进程退出后变为 Z 状态,那是如何处理的呢?

int main()
{
    pid_t pid = fork();
    if(pid == 0)
    {
     	// 子进程
        int cnt = 500;
        while(cnt)
        {
            cout << "I am a child process, pid: " << getpid() << ", ppid: " << getppid() << ", cnt: " << cnt << "\n";
            cnt--;
            sleep(1);
        }
		exit(0);
    }
    else
    {
     	// 父进程
        int cnt = 5;
        while(cnt)
        {
            cout << "I am a parent process, pid: " << getpid() << ", ppid: " << getppid() << ", cnt: " << cnt << "\n";
            cnt--;
            sleep(1);
        }
		exit(0);
	}
}

在这里插入图片描述

当父进程先退出了,留下子进程进行在跑的现象是,父进程退出那一刻,就立马被它的父进程(即 bash 回收了),所以也就检测不到父进程的进程信息了,但是子进程的 ppid 不再是一开始的父进程,而是变为了 1,无脑猜测,这个 pid 为 1的进程,就是我们的操作系统(也即 init 进程)!而我们把上述这种情况,父进程先退出,子进程就称之为“孤儿进程”!

所以现在也就可以回答一开始提出的问题了。父进程先退出,子进程就会被 1号 init 进程领养,所以当子进程退出,变为 Z 状态,自然就是由 1 号进程对其进行回收。而为什么要领养这个孤儿进程?如果不领养孤儿进程,那么当这些进程退出时,没有进程可以为其回收,释放系统资源,当这些进程越来越多,也就代表着系统中被占用的无用资源越来越多!所以必须要对孤儿进程进行领养,然后在其退出时将其资源释放回收。


到这里,linux 中常见的几个进程状态就已经交代完毕了,但是关于进程这个概念远远还没有结束。截止目前,我们知道了进程属性中的标识符(即 pid),知道了进程的状态(R, S, D, T, t, X, Z)。但是进程中还有一个 优先级 的概念,同样是进程中相当重要的组成信息,也会在之后的文章中进行介绍。

如果感觉该篇文章给你带来了收获,可以 点赞👍 + 收藏⭐️ + 关注➕ 支持一下!

感谢各位观看!

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

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

相关文章

【hbz分享】-springboot启动时做了哪些事情

spring启动类启动时的流程 先调用SpringApplication完成一系列初始化操作 先把启动类保存起来&#xff0c;就是带有main函数的那个类&#xff0c;把这个保存起来保存应用类型&#xff0c;是Servlet还是Ractive通过getSpringFactoriesInstances(BootstrapRegistryInitializer.…

<数据集>战斗机识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;7903张 标注数量(xml文件个数)&#xff1a;7903 标注数量(txt文件个数)&#xff1a;7903 标注类别数&#xff1a;43 标注类别名称&#xff1a;[F16, Mig31, F35, F18, SR71, A10, A400M, AG600, J20, F4, C17, Tor…

C语言程序设计之基础易错题锦集2

C语言程序设计之基础易错题锦集2 自加自减代码2_0_1运行结果2_0_1代码2_0_2运行结果2_0_2 问题2_1解答2_1 问题2_2结果2_2 问题2_3结果2_3 问题2_4结果2_4 问题2_5结果2_5 问题2_6结果2_6 自加自减 代码2_0_1 #include<stdio.h>main(){int a,b,c,d;abcd10;printf("…

【枚举 图论】2242. 节点序列的最大得分

本文涉及知识点 枚举 图论知识汇总 LeetCode 2242. 节点序列的最大得分 给你一个 n 个节点的 无向图 &#xff0c;节点编号为 0 到 n - 1 。 给你一个下标从 0 开始的整数数组 scores &#xff0c;其中 scores[i] 是第 i 个节点的分数。同时给你一个二维整数数组 edges &…

区分虚拟网卡和物理网卡

枚举注册表网卡信息 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}读取没一项的Characteristics、NetCfgInstanceId信息Characteristics & NCF_PHYSICAL 即为物理网卡 Characteristics值 类型值说明NCF_VIRTUAL0x01…

STM32L051K8U6-HAL-LED闪烁设计

HAL三步法&#xff1a; 1、配置下载线 2、配置晶振 3、配置时钟 注意&#xff1a;中断优先级&#xff08;这里防止HAL_Delay卡死&#xff0c;详细请看 http://t.csdnimg.cn/NQhQV&#xff09; 4、 配置灯引脚属性为输出模式。并设置标签为LED 生成代码&#xff1a;编写while里…

《关于触手 AI 图像合成算法的分析报告》

一、算法全周期行为分析 算法安全 信息内容安全&#xff1a;在图像生成过程中&#xff0c;需要确保所生成的图像内容不包含违法、有害、侵犯他人权益或违反道德规范的信息。例如&#xff0c;不能生成涉及暴力、色情、恐怖主义等内容的图像。信息源安全&#xff1a;对于输入的原…

警惕智能手机的“隐形眼”:如何保护我们的数字隐私堡垒

随着智能手机深入我们生活的方方面面&#xff0c;它变得无所不在&#xff0c;甚至无所不知。 但你是否意识到&#xff0c;你的手机可能正在悄无声息地“监听”你的一举一动&#xff1f; 从你的搜索习惯到日常对话&#xff0c;手机的个性化推荐系统正不断收集你的数据。 本文…

参考图片神器《PureRef》,带下载。

画画、建模或者做设计看参考时&#xff0c;是否经常为不能同时共存两个页面而苦恼。 今天就给大家推荐一个能解决这个问题得软件——PureRef 下载地址&#xff1a;PureRef 2.0汉化版 汉化版2.0 蓝奏云&#xff1a; https://wwz.lanzouq.com/iyUTy1zt2b4d 下面是一些软件快…

UWA Gears兼容性数据公开

UWA最新发布了无SDK性能分析工具 - UWA Gears。该工具能够实时监测应用的CPU和GPU性能&#xff0c;无需代码改动即可掌握性能动态。此外&#xff0c;Gears还能截取应用的渲染画面进行深度分析&#xff0c;帮助您快速找到性能瓶颈并进行精准优化。 本篇内容为开发者提供了Gears…

【LVS】防火墙标签解决轮询错误

实验&#xff1a; 测试&#xff1a; 实验&#xff1a; 两个服务端下载软件在重启httpd lvs 标记多端口 多端口自动识别 测试 防火墙标记解决轮回问题

关于IAR的ICF编程操作

最近有一个项目需要对ICF进行外部编程。两个工程引用相同的ICF&#xff0c;通过外部输入参数来区分内部的地址范围。通过相关资料的研究&#xff0c;cmake可以通过参数导入一个变量来就觉这个问题。后来参考IAR手册发现可以在IDE中定义. 例子&#xff1a; icf文件&#xff1a…

Java Kafka消费者组位移重设深度解析与实践

简介 在现代的分布式系统中&#xff0c;消息队列扮演着至关重要的角色。Apache Kafka&#xff0c;以其高吞吐量、高可靠性和优秀的容错性&#xff0c;成为了众多企业的首选消息系统。在使用Kafka过程中&#xff0c;消费者组位移的管理是一个常见且关键的议题。本文将深入探讨K…

Excel中的高效查找利器:VLOOKUP函数深度解析与应用实战

文章目录 前言一、VLOOKUP基础应用二、常见用法1.精确匹配2.近似匹配3.反向查找4.多条件查找5.屏蔽错误值6.关键字查找&#xff08;模糊查找&#xff09;7.文本数值混合查找8.去除空格查找 前言 VLOOKUP函数是Excel中用于在数据表中进行垂直查找的强大工具。它能根据用户指定的…

html+css+js网页设计 中国电信1个页面(带js)

htmlcssjs网页设计 中国电信1个页面&#xff08;带js&#xff09; 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xf…

Android 文件上传与下载

在实际开发涉及文件上传不会自己写上传代码&#xff0c;一般 会集成第三网络库来做图片上传&#xff0c;比如android-async-http&#xff0c;okhttp等&#xff0c;另外还有七牛也提供 了下载和上传的API。 1.项目用到的图片上传的关键方法&#xff1a; 这里用到一个第三方的库…

ChatGPT辅助论文写作各阶段提示词分享

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 随着人工智能技术的迅速发展&#xff0c;ChatGPT作为一种强大的语言模型&#xff0c;已经在各个领域展现出其独特的应用价值。在学术论文写作过程中&#xff0c;ChatGPT不仅可以帮助研究…

细节持续跟新

1.input的自带光标如何去除 2.阻止事件冒泡 3.获取父亲兄弟的innertext 4.画表格 参考博主链接 前端-HTML表格制作_哔哩哔哩_bilibili 美化

[CSCCTF 2019 Qual]FlaskLight (jinja2模版注入)

两种方法&#xff1a; 1.工具法 进来看见flask到处飘&#xff0c;估计就是ssti ctrlU打开发现两行注释提示GET方式传递参数search 这种有参数的我先直接丢fengjing扫了一下&#xff0c;结果还真搞出来&#xff0c;这工具还是挺牛的&#xff0c;就是没参数的时候搞不了 fengj…

在 Ubuntu 24.04 LTS 上安装 MySQL 8

1. 更新系统软件包 在开始安装 MySQL 之前&#xff0c;确保你的系统软件包是最新的。 sudo apt update sudo apt upgrade -y 2. 添加 MySQL APT 存储库 首先&#xff0c;下载 MySQL APT 存储库的包&#xff1a; wget https://dev.mysql.com/get/mysql-apt-config_0.8.17-1…