【Linux】进程状态(RSDT 阻塞 僵尸 孤儿)

news2024/11/25 22:39:41

目录

进程状态

进程状态的查看

R和S 运行状态

T/t 暂停状态

kill命令

D (disk sleep)状态、

Z 状态(僵尸状态)

孤儿状态

运行状态

阻塞状态


 

进程状态

一个进程通常有三种状态

就绪状态(Ready):表示进程已经具备运行所需要的一切条件,只需要等待CPU的分配就可以运行。进程处于就绪状态时,通常会被添加到就绪队列,等待调度器分配CPU资源。

运行状态(Running):表示进程正在被CPU执行。处于运行状态的进程正在使用CPU进行计算或其他操作。

阻塞状态(Blocked):表示进程因为某些原因暂时无法继续执行,需要等待一些特定条件的解除之后才能继续运行。例如,当进程等待I/O操作完成或者等待某个资源可用时,会转入阻塞状态。进程在阻塞状态时,通常会被移动到阻塞队列中,等待条件的满足

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)

下面的状态在Kernel源代码里定义:

 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 */
};

 

进程状态实质是结构体task_struct内部的一个属性。通过宏定义的方式进行描述以及更改进程状态

#define RUN 1
#define SLEEP 2  
#define STOP 3
 
struct task_struct
{
    // 内部的一个属性
    int status;
}
 
struct task_struct process1; //创建进程
process1.status=RUN;//设置进程状态

进程状态的查看

 while :; do ps axj | head -1 && ps axj | grep testStatus | grep -v grep; sleep 1;done 

R和S 运行状态

❍ R运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。

❍ S睡眠状态(sleeping)意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠)

通过C语言代码进行验证,依旧使用makefile工具

makefile代码:

bin=testStatus
src=testStatus.c
$(bin):$(src)
        gcc -o $@ $^ -std=c99
.PHONY:clean
clean:
        rm -f $(bin)

testStatus.c代码:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
 
int main()
{
	while (1)
	{
		printf("I am a process,pid: %d\n", getpid());
	}
	return 0;
}

通过运行结果我们i可以看到,我们的进程一直在运行,但是进程状态是S+状态,也就是休眠状态,可是按照我们自己的理解,程序正在运行不应该是R(运行状态)吗?为什么这里是S+状态呢?

这是因为:printf的本质是往显示器上进行打印;而程序的运行是在千里之外的云服务器上的,最终打印出来的信息显示到我们本地的显示器上;根据冯诺依曼体系结构,显示器是一个外设,所以CPU在跑当前的程序时,把数据写入到我们当前的内存中,打印数据的顺序:先写入到内存里,再刷新到外设这里。可是我们无法保证每次打印的时候,显示器的状态都是就绪的,因为程序是CPU跑的,CPU的运算速度要比显示器本身的速度要快的多,这种快慢人是无法感知的,所以进程在被调度的时候,要访问显示器的资源,因为资源要一直在显示器上打,所以大部分时间,我们的进程一直在等待我们的设备资源是否准备就绪。所以也就是为什么总是S(休眠状态)

注意: 

./testStatus & # 在执行可执行程序后面加&符号,为在后台运行,跑起来后面不带+号。+号表示在前台还是后台运行,以什么为参考系后面说。后台运行后面有数字(pid),且ctrl +c 不能中断进程,需用kill -9 pid杀掉进程。

T/t 暂停状态

kill命令
	kill  [-s <信号名称或者编号>][程序]   或   kill  [-l <信息编号>]

功能:给指定命令发信号

常见选项:-l <信息编号> : 若不加<信息编号>选项,则 -l 参数会列出全部的信息名称。

总共有64个信息编号,其实上面的这些东西都是宏,我们已经会使用 -9 杀死进程,下面我们会用到 -18(SIGCONT)进程继续 以及 -19(SIGSTOP)暂停进程

一个进程被暂停也会自动变为后台(只能使用kill -9杀死进程)

 上面运行的是T状态,接下来我们来看 t 状态

❍ t (tracing stop) : 当前的进程因为被追踪而暂停了

这种情况可以在调试代码的时候遇见,因为调试的过程,中间就有暂停的动作

D (disk sleep)状态、

❍ D (disk sleep): Linux系统比较特有的一种进程状态,不可被杀,深度睡眠,不可中断睡眠

◉ 一个进程要将1个G的数据存储到磁盘,根据冯诺依曼体系结构可以知道,本质是把数据从内存交给外设,由于速度差,进程需要等待硬盘资源把数据写入完毕,此时进程处于S状态,又因为操作系统管理进程,当系统整个的内存资源严重不足时Linux操作系统有权利杀掉进程来释放空间,然后操作系统把A进程杀掉,但是此时B进程要给硬盘写入数据,硬盘需要去照顾B进程,导致A进程写入数据失败了,1GB的数据丢失了,如果这个数据是银行的转账记录,那么可能造成很大的影响。

◉ 为了避免这种情况,如果进程在等待硬盘资源时,进程需要将自己的状态设为D状态:不可被杀深度睡眠,不可中断睡眠。

◉ 我们一般不会遇到这种情况,从事系统管理、运维、存储等工作可能会遇到。

 

杀死D状态的方法:

1️⃣ 让进程自己醒来

2️⃣ 重启,重启不行则断电

Z 状态(僵尸状态)

僵尸状态:当一个 Linux 中的进程退出的时候,一般不会直接进入 X 状态(死亡,资源可以立马被回收),而是进入 Z 状态。如果父进程不对其进行回收,则会一直处于僵尸状态,也就是子进程先于父进程退出

就好比如:在杀人案中,一名尸体躺在地下,这时候你发现了,你连忙开始报警,报警后,警察来的第一件事不是移走尸体,而是进行封锁现场,让尸体原地待着,等待法医进行检验后,再进行移动。在这个让尸体原地待着的过程,就是Z状态,僵尸状态

以下是创建僵尸进程的代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main() {
    pid_t id = fork();
    if (id < 0) {
        perror("fork");
        return 1;
    } else if (id == 0) { // 子进程
        printf("子进程[%d]开始运行...\n", getpid());
        sleep(5);
        printf("子进程[%d]退出...\n", getpid());
        exit(0);
    } else { // 父进程
        printf("父进程[%d]正在睡眠...\n", getpid());
        sleep(15); // 父进程延迟回收子进程
    }
    return 0;
}

为什么父进程不回收子进程PCB?

1.父进程要知道子进程为什么要退出,父进程要获取子进程退出的信息。

2.独立性,父进程只读取子进程的信息,不对信息做修改,依旧保持独立性。

僵尸进程的危害

僵尸进程虽然不再运行,但它们仍然占用系统资源(如进程控制块task_struct)。如果父进程不及时回收子进程,会导致系统资源浪费,甚至内存泄漏。

避免僵尸进程

可以通过以下方式:

1️⃣ 父进程及时调用wait()waitpid()回收子进程。

2️⃣ 使用信号处理机制,在子进程退出时通知父进程进行回收。

孤儿状态

孤儿进程:即父进程不是休眠,而是比子进程提前结束,造成子进程不归原父亲管理,原子进程父亲变为1号进程,相当于被OS领养了

测试代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
int main(void) {
    pid_t id = fork();
    if (id == 0) {
        // child
        int cnt = 5;
        while (1) {  // 死循环,孩子进程就不退了
            printf("我是子进程,我还剩下 %ds\n", cnt--);
            sleep(1);
        }
        printf("我是子进程,我已经变僵尸了,等待被检测\n");
        exit(0);
    }
    else {
        // father
        int cnt = 3;
        while (cnt) {
            printf("我是父进程,我: %d\n", cnt--);
            sleep(1);
        }
        printf("我是父进程,我先提前溜了\n");
        exit(0);
    }
}

 

疑问:父进程退出,为什么父进程没有变成僵尸?我们怎么没有看到父进程 为Z?  

◉ 那是因为父进程的父进程是bash ,它会自动回收它的子进程,也就是这里的父进程。这里之所以没有看到父进程变成僵尸,是因为被 bash 回收了, z->x 的状态很快,所以你没看到。 ​

◉ 那为什么刚才我自己代码中的父进程创建的子进程,父进程没有回收子进程呢?那是因为你的代码压根就没有写回收,所以你的子进程就没有回收。

并且这里我们也发现 子进程由 S+ -- > S,此刻退出子进程也必须使用kill - 9;

运行状态

进程只要在运行队列中,就叫做运行态

每个task_struct对应一个时间片,当执行程序时间到了之后,会自动切换到下一个进程,也就是CPU的执行是基于时间片进行轮转调度的,在一个时间段内同时得以推进代码,就叫做并发

如果我们不止一个CPU,那么任何时刻,都同时有多个进程在真的同时运行,我们叫做并行

 

阻塞状态

在操作系统中,阻塞状态(Blocked State)是进程生命周期中的一个状态,当进程等待某些事件发生而无法继续执行时,它就会进入阻塞状态。

关于进程: ① 一个进程使用资源的时候,可不仅仅是在申请 CPU 资源 ② 进程可能会申请其它资源:磁盘、网卡、显卡,显示器资源…… 如果我们申请 CPU 资源无法暂时无法得到满足,这就需要排队的 "运行队列" 。那么如果我们申请其他慢设备的资源呢?是需要排队的(task_struct 在进程排队)。

当访问某些资源(磁盘,网卡等),如果该资源暂时没有准备好,或者正在给其他进程提供服务,那么此时:

① 当前进程要从 runqueue 中逐出。

② 将当前进程放入对应设备的描述结构体中的waitqueue 。

注意:并不是只有等待硬件资源的进程才处于阻塞状态,一个进程等待另一个进程就绪、一个进程等待软件资源就绪等也是阻塞状态。

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

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

相关文章

Qt 去掉QDialog对话框的问号

QT 对话框的问号是什么&#xff1f; QDialog默认的window flag中包含了Qt::WindowContextHelpButtonHint,这个flag意思是在窗口上提供“上下文帮助”按钮 使用方式/调用方式 void QWidget::setWhatsThis(const QString &)比如&#xff1a; ui->lineEdit_1->setWh…

用亚马逊AI代码开发助手Amazon Q Developer开发应用(上篇)

快用人工智能帮程序员写代码&#xff01;今天小李哥就来介绍亚马逊推出的国际前沿人工智能AI代码开发助手Amazon Q Developer。目前该代码助手在Hugging Face代码生成权威测试集SWE-bench中排名第一&#xff0c;可以根据我们的需求生成整个代码项目&#xff0c;并可以帮助我们解…

C++入门基础,看这篇就足够了!

&#x1f308;个人主页&#xff1a;Yui_ &#x1f308;Linux专栏&#xff1a;Linux &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;数据结构专栏&#xff1a;数据结构 &#x1f308;C专栏&#xff1a;C 文章目录 0.前言1. C的关键字2.命名空间2.1 命名空间的定…

vue 中计算属性可以接收参数

代码中的value就是接收的参数 计算属性要接收参数要写在返回的时候 computed: {isButtonDisabled() {return (value) > {const num parseInt(value);return isNaN(num) || num < 0}},},//计算属性aaa(){return (value) >{写逻辑return 返回值}} 使用 <el-butto…

【数学建模】国赛论文写作技巧教学——模型假设与变量说明

一、模型假设 1、内容要求 模型假设是建立数学模型中非常关键的一步&#xff0c;这会关系到模型的成败和优劣。所以&#xff0c;应该细致地分析实际问题&#xff0c;从大量的变量中筛选出最能表现问题本质的变量&#xff0c;并简化它们的关系。由于假设一般不是实际问题直接提…

2024Hvv漏洞汇总(128个POC)

2024Hvv漏洞整理&#xff08;128个POC&#xff09; ​&#xff08;网上漏洞零零散散&#xff09;下面是收集到的且有POC的漏洞整理合集&#xff0c;鄙人分了三种格式供各位提取&#xff0c;下面贴上目录与图片&#xff0c;由于字数有点大&#xff0c;各位请移步网盘自行提取。…

MySQL 基础命令

目录 一、MySQL简介 1.MySQL 的主要特点包括 2.MySQL 的主要用途包括&#xff1a; 二、MySQL 基础命令 1. 基本操作 1.1 进入 1.2 选择数据库 1.3 修改密码 1.4 所有命令后面都要加 “;” 2. 创建 2.1 创建数据库 2.2 创建数据表 2.3 常见字段 3. 修改/更新 3.1…

[数据集][目标检测]街道乱放广告牌检测数据集VOC+YOLO格式114张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;114 标注数量(xml文件个数)&#xff1a;114 标注数量(txt文件个数)&#xff1a;114 标注类别…

关于LLC知识15

右手螺旋定则&#xff1a;四指指向电流的方向&#xff0c;拇指的方向就是磁通方向 变压器副边会产生一个和原磁通方向相反的磁通来阻碍它变大 这样原边绕组的电感量会变小&#xff1a;U/Ldi/dt对应的电流会变大 电感量越大&#xff0c;抑制电流能量越强 原边开路时候&#x…

【贪心算法】区间类算法题(整数替换、俄罗斯套娃、重构字符串等、C++)

文章目录 1. 前言2. 算法题1.整数替换2.俄罗斯套娃信封问题3.可被三整除的最大和4.距离相等的条形码5.重构字符串 1. 前言 贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在每一步选择中都采取当前状态下最优决策的算法。贪心算法通常用来解决最优化问题&#xff0c…

sqlite数据插入效率

一、程序效率测试 时间相关接口&#xff1a; int gettimeofday(struct timeval*tv, struct timezone *tz); 功能&#xff1a;得到从1970年1月1日0时0分0秒到现在的秒数。<可以利用该函数来计算一个程序的运行时间&#xff0c;只需在程序前后调用该函数&#xff0c;…

安捷伦Agilent N9344C手持频谱分析仪

安捷伦Agilent N9344C手持频谱分析仪 安捷伦Agilent N9344C手持频谱分析仪&#xff08;HSA&#xff09; 主要特性和功能 获得专为现场使用设计的性能&#xff1a;便携耐用&#xff0c;无风扇设计&#xff1b;无论白天还是夜晚均可显示清晰的画面&#xff1b;电池使用时间为 4 …

大模型开发转行全攻略:必备知识、技能与学习路径详解,大模型零基础入门到精通

引言 随着人工智能和大模型&#xff08;如GPT-4、BERT等&#xff09;技术的快速发展&#xff0c;越来越多的专业人士希望转行进入这一领域。大模型开发涉及复杂的技术体系和多样的应用场景&#xff0c;对从业者的知识和能力提出了较高要求。本文将详细解析转行大模型开发所需的…

CasaOS系统本地安装Gopeed高速下载软件并实现异地远程访问下载文件

文章目录 前言1. 更新应用中心2.Gopeed安装与配置3. 本地下载测试4. 安装内网穿透工具5. 配置公网地址6. 配置固定公网地址 前言 本文主要介绍如何在轻NAS系统CasaOS小主机中安装支持全平台的高速下载器Gopeed&#xff0c;并结合内网穿透工具配置公网地址实现远程访问本地主机…

java知识点——I/O输入输出处理(二)

读取字符流&#xff1a; 由于字符输入流的read()方法返回的是int类型的值&#xff0c;如果想获得字符就需要进行强制类型转换&#xff0c;所以输出语句中将变量len强转为了char类型。 public static void main(String[] args) throws IOException {//创建FileReader对象FileRe…

PHP一体化解决方案高效整合与优化学校管理系统小程序源码

一体化解决方案&#xff0c;让学校管理系统焕发新生✨ &#x1f3eb; 开篇&#xff1a;传统管理的瓶颈与挑战 在快节奏的教育时代&#xff0c;传统的学校管理系统是否让你感到力不从心&#xff1f;&#x1f914; 信息孤岛、流程繁琐、效率低下...这些问题是否正困扰着你的工作…

巴黎奥运会引发体育健身热潮:气膜体育馆成为新宠—轻空间

随着巴黎奥运会的成功举办&#xff0c;全球范围内掀起了一股体育健身的热潮。各地的健身场所迎来了前所未有的参与热情&#xff0c;其中&#xff0c;融合了体育、娱乐、休闲等多种业态的综合气膜体育馆因其独特的优势&#xff0c;迅速成为群众健身的新宠&#xff0c;成为了大众…

PHP一键创建全球参与探索现代在线投票系统

一键创建全球参与探索现代在线投票系统 &#x1f310;✨ &#x1f680; 开篇&#xff1a;解锁全球互动新纪元 在这个数字化飞速发展的时代&#xff0c;每一个声音都值得被听见&#xff0c;每一份意见都能跨越山海相连。想象一下&#xff0c;只需轻轻一点&#xff0c;就能发起…

如何读懂以太坊源代码

以下是一个学习以太坊源代码的清晰思路&#xff1a; 一、前期准备 基础知识储备&#xff1a; 熟悉区块链的基本概念&#xff0c;如区块、交易、共识机制、哈希函数等。了解 Go 语言&#xff08;以太坊主要使用 Go 语言编写&#xff09;的基本语法和编程概念。 工具准备&#x…

包装和类练习(1)

目录 1.移除元素 2.删除有序数组中的重复项 3.合并两个有序数组 4.实现ArrayList类 4.下列在Java语言中关于数据类型和包装类的说法&#xff0c;正确的是&#xff08;&#xff09; 5. boolean类型没有包装用的类&#xff0c;这句话是否正确&#xff1f; 1.移除元素 这里使用…