Linux进程状态

一.基础知识

在进入到Linux进程状态学习之前,我们先学习一些基础知识:

1.1并发和并行

并发: 在单CPU的计算机中,并不是把当前进程执行完毕之后再执行下一个,而是给每个进程都分配一个时间片,基于时间片进行进程调度的过程叫做并发。
并行: 多个进程在多个CPU下分别、同时运行叫做并行。

1.2 时间片

Linux/Windows等民用操作系统,都是分时操作系统,他们会给一个进程规定一个时间,当这个时间过去了,这个进程就必须从CPU上剥离下来,换成另外一个进程运行,这个时间就叫做时间片
分时操作系统的特点:调度任务追求公平。
实时操作系统:任务一旦执行,就优先并尽快使其执行完毕。

二.进程状态

在了解Linux进程状态之前,我们先了解一下进程的状态。
在操作系统的课程中,我们有如下一张图:
在这里插入图片描述

这张图宏观的描述了操作系统的状态,对于不同的操作系统,都有以上的这些状态,但是不同的操作系统对这些状态的处理方式是不同的。
下面,我们来详细的讲解一下等待。

等待

阻塞的本质是等待!

对于每个CPU,操作系统都要给它提供一个叫做运行队列的东西(FIFO),每次执行一个进程,就是把这个进程的task_struct链入运行队列中,CPU在处理进程时,就只需要到运行队列去取头节点即可。
在这里插入图片描述

当一个进程的时间片用完了之后,就删除队列的头节点,然后再将这个节点链接到队尾,之后执行下一个task_struct。
在这里插入图片描述
当一个进程处于运行队列中时,我们就称这个进程为运行状态,虽然可能这个进程实际上并没有被CPU执行。
那么,阻塞状态是什么样的呢?
在计算机中,大多数都是在做IO(外设访问)的。就譬如scanf函数,如果我们不输入数据的话,进程就获取不到数据,但,CPU不会一直等待这个进程。此时这个进程就会被设置为阻塞状态,需要等待底层硬件准备好,才会被重新放入运行队列中。
也就是说,阻塞状态其实就是在等待硬件
而,操作系统管理硬件采取的态度也是:先描述,再组织。
最终也会呈现出一个结构体的形式:

struct device
{int type;//硬件类型int status;//硬件状态
//其他属性struct device* next//下一个硬件task_struct waitQueue;//等待队列
}

如下图:
在这里插入图片描述

还有一种状态叫做阻塞挂起
阻塞期间,进程不会被调度,但对应进程的PCB和代码以及数据也是会占用内存的,若进程越来越多,则计算机的内存资源迟早不够用,那么,此时,操作系统为了保证整个系统的安全,就会将进程的代码和数据换出到磁盘中;当进程不阻塞时,操作系统再将对应的代码和数据换入到内存当中。
在这里插入图片描述
我们现在将这张图整合起来。如下:

在这里插入图片描述
我想,现在大家就已经明白了等待的本质。

三.Linux进程

现在,我们讲解Linux的进程状态:
在Linux的源代码中,有如下状态:

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 */       //僵尸状态};

R和S状态

R状态:运行状态,进程链接在运行队列中的状态
S状态:休眠状态,进程阻塞挂起的状态。可中断睡眠(浅睡眠,可以被kill杀死)

当调用printf时,由于会一直做IO操作,就会一直等待外设,也就是浅度睡眠状态。
而一直执行一个空语句时,就会是R状态。
在这里插入图片描述

D状态

D状态也就是disk sleep,这也是睡眠状态的一种,是不可中断的睡眠,也就是深度睡眠。
这是专门为磁盘设计的状态。
为了保护访问磁盘的进程,禁止操作系统“杀掉”该进程,该进程就会处于D状态。
至于为什么不可以杀死这个进程,打个比方。
比方说,一个进程正在将重要数据写入磁盘,数据只写到一半时,进程突然被杀死,那么磁盘上可能会留下损坏的文件或未完成的事务。为了解决这个问题,Linux 设计了 D 状态,使进程在 I/O 完成之前不会被终止,从而保证数据的完整性和系统的稳定性。
值得一提的是,如果一个系统的大量状态在D状态下,那么它距离崩溃就不远了~~~

T状态和t状态

T状态是暂停状态,在认识这个状态之前,我们先认识两个信号。
在这里插入图片描述

19号信号,可以让指定进程暂停,从而变成T状态
18号信号,可以让指定进程继续执行,此进程的状态就变成了S(浅度睡眠)

在这里插入图片描述
然后,我们使用18号信号恢复它。

在这里插入图片描述
我们发现,用18号信号恢复它之后就变成了R状态,而不是之前查出来的R+,这是什么意思呢?

带+号的是前台进程
不带+号的是后台进程

想要杀死后台进程,我们只能通过kill -9 pid来杀死。
另外,一个进程被暂停又被运行后,会变成后台程序运行。

而t状态是一种调试状态,就譬如使用gdb进入调试的程序,就会以t状态运行。

X状态、Z状态

X状态是死亡状态,当一个进程运行结束后就会进入X状态。不再描述
下面,我们详细的来解释一下Z状态。
Z状态,即僵尸状态。是处于死了之后还没人来管的状态,就譬如人死了法医还没来验尸的时候。
对于进程而言也是一样的,当一个进程return了之后,会返回一个退出码。

退出码

而这个退出码的信息,规定了这个进程退出的状态,就譬如0为正常退出,非0为异常退出。
我们先简单的谈一下退出码:
Linux系统中规定了一套退出码,它规定了0是正常退出,非0是异常退出。
而返回的值非0值共有256个。也就是1-255。
每一个非0的退出码都代表一类错误原因。
而我们程序员也可以自己维护一套退出码。
在Linux中,查最近一条进程退出信息的命令是:echo $?

在这里插入图片描述

僵尸状态

那么,为什么要返回一个退出码呢?
是因为,父进程/操作系统要知道子进程把任务执行的怎么样。
那么,什么是僵尸状态呢?

  • 当一个进程退出时,它的代码和数据会被释放,但是它的任务结构体还在,task_struct中存放着该进程的退出信息。
  • 当一个进程退出并且父进程还没有读取到子进程的返回码时,就会产生僵尸进程。
  • 僵尸进程会以终止状态保持在进程表中,并且会一直等待父进程读取退出状态代码。
  • 如果父进程不回收子进程,就会造成资源的浪费,因为数据结构本身就占据内存资源。此时就会造成内存泄漏(系统级)

现在,我们就知道了僵尸状态是什么样的了,现在我们写一段代码测试一下:

#include <iostream>
#include <unistd.h>
int main()
{printf("I am parent process.My pid is %d,My ppid is %d."getpid(),getppid());pid_t id=fork();if(id==0){int cnt=10;while(cnt--){printf("I am Child process.My pid is %d,My ppid is %d."getpid(),getppid());sleep(1);}}else if(id>0){while (1){printf("I am parent process.My pid is %d,My ppid is %d."getpid(),getppid());sleep(1);}}return 0;
}

我们果然在这里观察到了Z状态,它变成了僵尸状态。
在这里插入图片描述
循环查询代码:

while :; do ps ajx|head -1 && ps ajx|grep proc | grep -v grep;sleep 1;done

下面,再来一个问题,当父进程退出,子进程存在,这又是什么状态呢?

孤儿状态

儿子还在,但是parent却没了,那么这个儿子就变成了孤儿状态。
没错,这个状态就叫做孤儿状态。
下面,我们改一下代码:

 #include <stdio.h>2 #include <unistd.h>3 int main()4 {5     printf("I am parent process.My pid is %d,My ppid is %d.\n",getpid(),getppid());6     pid_t id=fork();7     if(id>0)8     {9         int cnt=10;10         while(cnt--)11         {12             printf("I am parent process.My pid is %d,My ppid is %d.\n",getpid(),getppid(13             sleep(1);14         }15     }16     else if(id==0)17     {18         while (1)19         {20         printf("I am parent process.My pid is %d,My ppid is %d.\n",getpid(),getppid()); 21         sleep(1);22         }23     }24     return 0;25 }

在这里插入图片描述
我们发现,当父进程死亡之后,子进程的父进程会变成1,也就是操作系统。
我们可以用top查看:

top

在这里插入图片描述
当父进程退出时,操作系统会领养子进程,以便接收子进程的退出信息并回收进程。这个进程被称为孤儿进程。孤儿进程在后台运行。

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

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

相关文章

【含文档+PPT+源码】基于SpringBoot电脑DIY装机教程网站的设计与实现

项目介绍 本课程演示的是一款 基于SpringBoot电脑DIY装机教程网站的设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套…

【免费】2000-2020年各省地区生产总值指数数据

2000-2020年各省地区生产总值指数数据 1、时间&#xff1a;2000-2020年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;行政区划代码、地区、年份、地区生产总值指数(上年100) 4、范围&#xff1a;31省 5、指标说明&#xff1a;地区生产总值指数&#xff0…

【大厂AI实践】清华:清华古典诗歌自动生成系统“九歌”的算法

【大厂AI实践】清华&#xff1a;清华古典诗歌自动生成系统“九歌”的算法 &#x1f31f; 嗨&#xff0c;你好&#xff0c;我是 青松 &#xff01; &#x1f308; 自小刺头深草里&#xff0c;而今渐觉出蓬蒿。 文章目录 **01 自动作诗缘起****1. 诗歌自动写作** **02 九歌的模型…

实验:k8s+keepalived+nginx+iptables

1、创建两个nginx的pod&#xff0c;app都是nginx nginx1 nginx2 2、创建两个的pod的service 3、配置两台keepalived的调度器和nginx七层反向代理&#xff0c;VIP设置192.168.254.110 keepalived调度器master keepalived调度器backup 两台调度器都配置nginx七层反向代理&#…

基于eRDMA实测DeepSeek开源的3FS

DeepSeek昨天开源了3FS分布式文件系统, 通过180个存储节点提供了 6.6TiB/s的存储性能, 全面支持大模型的训练和推理的KVCache转存以及向量数据库等能力, 每个客户端节点支持40GB/s峰值吞吐用于KVCache查找. 发布后, 我们在阿里云ECS上进行了快速的复现, 并进行了性能测试, ECS…

DeepSeek掘金——DeepSeek-R1图形界面Agent指南

DeepSeek掘金——DeepSeek-R1图形界面Agent指南 本文将指导你完成设置 DeepSeek R1 和 Browser Use 的过程,以创建能够执行复杂任务的 AI 代理,包括 Web 自动化、推理和自然语言交互。 开源大型语言模型 (LLM) 的兴起使得创建可与 OpenAI 的 ChatGPT Operator 等专有解决方案…

K8S学习之基础六:k8s中pod亲和性

Pod节点亲和性和反亲和性 podaffinity&#xff1a;pod节点亲和性指的是pod会被调度到更趋近与哪个pod或哪类pod。 podunaffinity&#xff1a;pod节点反亲和性指的是pod会被调度到远离哪个pod或哪类pod 1. Pod节点亲和性 requiredDuringSchedulingIgnoredDuringExecution&am…

Lua | 每日一练 (4)

&#x1f4a2;欢迎来到张胤尘的技术站 &#x1f4a5;技术如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 Lua | 每日一练 (4)题目参考答案线程和协程调度方式上…

数据结构:二叉搜索树(排序树)

1.二叉搜索树的定义 二叉搜索树要么是空树&#xff0c;要么是满足以下特性的树 &#xff08;1&#xff09;左子树不为空&#xff0c;那么左子树左右节点的值都小于根节点的值 &#xff08;2&#xff09;右子树不为空&#xff0c;那么右子树左右节点的值都大于根节点的值 &#…

SpringBoot快速入门

快速入门 1). 创建springboot工程&#xff0c;并导入 mybatis的起步依赖、mysql的驱动包、lombok等。 项目工程创建完成后&#xff0c;自动在pom.xml文件中&#xff0c;导入Mybatis依赖和MySQL驱动依赖。如下所示&#xff1a; 2). 数据准备&#xff1a;创建用户表user&#xf…

DataWorks (数据工厂)介绍

介绍 DataWorks 是阿里云推出的一体化大数据开发与治理平台&#xff0c;曾用名"数据工厂""大数据开发套件" 最新版本是3.0 它是一套基于MaxCompute&#xff08;原ODPS&#xff09;的DW(数据仓库)解决方案&#xff0c;它集成了阿里多年的DW实施经验&…

信息技术知识赛系统设计与实现(代码+数据库+LW)

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装信息技术知识赛系统软件来发挥其高效地信息处理的作用&…

VirtualBox虚拟机转VM虚拟机

前言&#xff1a;部分靶机只适用于VirtualBox&#xff0c;VM打不开VirtualBox的文件&#xff0c;所以需要进行转换 前置条件&#xff1a;本机已经下载VM和VirtualBox 第一步&#xff1a;文件转换 找到VirtualBox.exe所在位置&#xff0c;启动cmd窗口 文件转换的命令&#xf…

ArcGIS操作:11 计算shp矢量面的质心坐标

1、打开属性表 2、添加字段 3、设置字段名称、类型 4、选择创建的字段&#xff0c;计算几何 5、选择属性质心的x坐标、坐标系&#xff08;y坐标同理&#xff09; 注意&#xff1a;计算坐标一般使用的是地理坐标系&#xff08;投影坐标系转地理坐标系教程&#xff1a;ArcGIS操作…

使用 DeepSeek 生成流程图、甘特图与思维导图:结合 Typora 和 XMind 的高效工作流

在现代工作与学习中&#xff0c;可视化工具如流程图、甘特图和思维导图能够极大地提升信息整理与表达的效率。本文将详细介绍如何使用 DeepSeek 生成 Mermaid 文本&#xff0c;结合 Typora 快速生成流程图和甘特图&#xff0c;并通过 Markdown 格式生成思维导图&#xff0c;最终…

【Cadence仿真学习笔记】ADS Dynamic Link报错model is reserved的解决办法

首先创建好原理图 创建symbol 在library manager下就会出现symbol了 在Cadence的CIW窗口中运行ADS dynamic link 打开ADS后&#xff0c;创建对应的cellview 加入控件OPTIONS 加入网表netlist 这个时候的Netlist没有路径 点击加载symbol 把原来的netlist include删掉…

【二.提示词工程与实战应用篇】【1.提示词工程入门:AI对话的艺术】

大家好,今天咱们来聊聊一个特别有意思的话题——提示词工程。你可能已经听说过这个词,或者在使用AI工具时不经意间接触过它。但提示词工程到底是什么?它为什么这么重要?咱们今天就来深入探讨一下,看看它是如何影响我们与AI的对话,以及如何在实际应用中发挥作用的。 什么…

[密码学实战]Java实现国密(SM2)密钥协商详解:原理、代码与实践

一、代码运行结果 二、国密算法与密钥协商背景 2.1 什么是国密算法&#xff1f; 国密算法是由中国国家密码管理局制定的商用密码标准&#xff0c;包括&#xff1a; SM2&#xff1a;椭圆曲线公钥密码算法&#xff08;非对称加密/签名/密钥协商&#xff09;SM3&#xff1a;密码…

unity lua属性绑定刷新

我们现在有一个 角色属性类叫heroModel,内容如下,当heroModel中的等级发生变化的时候&#xff0c;我们需要刷新界面显示等级信息&#xff0c;通常我们是在收到等级升级成功的协议的时候&#xff0c;发送一个事件&#xff0c;UI界面接受到这个事件的时候&#xff0c;刷新一下等级…

制服小程序的“滑手”:禁用页面左右滑动全攻略

哈哈&#xff0c;看来你已经很聪明地发现了小程序中左右滑动的“顽皮”行为&#xff01;&#x1f604; 没错&#xff0c;我们可以通过设置 disableScroll 属性来“管教”它&#xff0c;同时结合 CSS 样式让页面既禁得住横向“乱跑”&#xff0c;又能顺畅地上下滚动。你的方案已…