[Linux 进程(二)] Linux进程状态

在这里插入图片描述

文章目录

  • 1、进程各状态的概念
    • 1.1 运行状态
    • 1.2 阻塞状态
    • 1.3 挂起状态
  • 2、Linux进程状态
    • 2.1 运行状态 R
    • 2.2 睡眠状态 S
    • 2.3 深度睡眠 D
    • 2.4 停止状态 T
    • 2.5 僵尸状态 Z 与 死亡状态 X
      • 孤儿进程

Linux内核中,进程状态,就是PCB中的一个字段,是PCB中的一个变量,一般是宏定义出的一批数字。
为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。下面是linux内核源码的状态定义。

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

再配上下面的图,我们看看各进程状态之间的转换:
在这里插入图片描述

状态的变化,本质就是修改整形变量。
看到这大家可能还是比较懵的,下面我们就来细看每一种状态。
首先我们先看教材上的进程状态,再具体到Linux下的进程状态。

1、进程各状态的概念

1.1 运行状态

每个CPU在系统层面都会维护一个运行队列。(n个CPU就会维护n个运行队列)
在这里插入图片描述
什么叫做运行状态?
只要在运行队列中的进程,状态都是运行状态。
只要是在运行队列中的进程,它的PCB中状态字段就是R,数据是准备就绪的,只等CPU运行了。

1.2 阻塞状态

进程 = 代码 + PCB(内核数据结构)。而我们的代码中,一定或多或少回访问系统中的某些资源(比如:磁盘、显示器、键盘、网卡等)。
我们下面举例来理解一下阻塞状态,下面是一整个链路,串起来理解:

1、当我们是C/C++代码,代码中有 scanf/cin,需要从键盘中输入时,我们用户就是不输入,键盘上的数据就是没有准备就绪的,这就是进程所要访问的数据没有就绪,即不具备访问条件,导致进程的代码无法向后执行。
2、访问的数据没有就绪,操作系统一定是最先知道的,因为操作系统是一款搞管理的软件,它管理计算机的所有软硬件。操作系统管理硬件,本质也是管理数据,“先描述,再组织”。
3、当进程在CPU中被运行的时候,用户一直不输入,这时访问的数据是没有就绪的,于是PCB就被操作系统从运行队列中放到硬件的等待队列中,PCB中状态字段就被改为 阻塞状态,然后去排队等待。一旦用户输入,数据状态立马就被改为了就绪状态,操作系统再将PCB放入到运行队列(将进程唤醒),并将PCB状态改为运行状态,CPU继续开始运行进程。
在这里插入图片描述

总结:
1、当PCB不在CPU所维护的运行队列,而在硬件的等待队列中,此时状态就是阻塞状态。
2、进程状态变化的本质:更改PCB中status整数变量; 将PCB链入到不同的列队中。
3、这里的所有过程,只和进程的PCB有关,与进程的数据代码都无关。
4、操作系统中,会有非常多的队列,运行队列、等待硬件的设备等待队列等。

这里我们也就不难想到,平时使用计算机时,启动了非常多的进程后,为什么会那么卡呢?
其实就是操作系统以我们能感知的时间里,将进程的状态不断在改变。

1.3 挂起状态

如果一个进程当前被阻塞了,这个进程等待的资源是没有就绪的,该进程就没有办法被调度。
如果此时,恰好 操作系统内的内存资源严重不足(前提) 了,怎么办?
此时我们阻塞进程的代码和数据就可以先写入磁盘中,等数据就绪后,再拷贝到内存中,这时就叫做 阻塞挂起状态(结果)这里将内存数据置换到磁盘,针对所有的阻塞进程。这个过程虽然慢了点,但是与资源严重不足将要宕机相比,慢点是可以接收的。

这里数据会被置换到swap分区。一般swap分区大小与内存大小差不多大,如果很大,swap分区很难被写满,内存稍微不足,操作系统就会将数据换出到swap分区,频繁的换出就会导致效率变慢。因此设置小点就会倒逼操作系统自己来处理,而不是频繁使用置换算法,提高效率。
当进程被os调度,曾经被置换出去的进程代码和数据,又要被重新加载到内存。
在这里插入图片描述

具体还有就绪挂起,在运行队列中,但是还没有被调度的进程,代码和数据被换出,等调度的时候再换入,这就是就绪挂起,这样会导致效率变低。

2、Linux进程状态

2.1 运行状态 R

  • R运行状态(running) : 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
    我们写一段C语言代码来跑一下,看看进程是什么状态。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{while(1){printf("Hello Linux, pid:%d\n", getpid());sleep(1);}return 0;
}

我们编译完代码后运行,并用 ps ajx 命令查进程,看看进程状态:

ps ajx | head -1 && ps ajx | grep mytest | grep -v "grep"

在这里插入图片描述
这里明明是运行着呢,为什么状态是S呢?
这是因为CPU跑代码很快,但是外设显示器的速度很慢,大多时间都是在等待显示器。这就是访问了外设,外设数据没有就绪,进程是阻塞状态。

我们去掉 printf 语句,不让代码去访问外设,直接运行,看到的就是R 运行状态了。
在这里插入图片描述
在这里插入图片描述

大家一定还有疑问,我们说的是R与S状态,但是查出来的却是R+与S+,这是怎么回事呢?
+表示的是前台进程的意思,所谓前台进程就是推在前台的,一旦启动我们的bash(命令行解释器)就无法在使用了,前台进程可以使用 ctrl+c 终止掉的。
在这里插入图片描述

后台进程就是跑在后台的,不影响我们bash的工作(输入命令可以执行),只能使用 kill -9 pid 来终止。后台进程的状态就没有+。
后台进程的启动:./exe &
在这里插入图片描述

2.2 睡眠状态 S

  • S睡眠状态(sleeping): 意味着进程在等待事件完成浅度睡眠,可以被终止掉,会对外部信号做出响应。(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
    我们写一段C语言代码,编译后运行:
    在这里插入图片描述
    在这里插入图片描述
    此时我们不输入,进程就阻塞了,在Linux中具体的状态就是S。
    在这里插入图片描述
    S状态可以被终止掉,或者可以再换到运行状态。

2.3 深度睡眠 D

  • D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
    D状态我们不好演示,我们举例讲一下,什么时候是深度睡眠状态。
    如果我们的进程是往磁盘中做写入操作的时候,写入的数据量很大,这时是磁盘在工作了,进程就休眠了,但是写入成功与否,磁盘还要给进程反馈。恰巧此时内存资源严重不足,置换算法也解决不了时,(Linux下)操作系统是可以杀进程的,它肯定是不会杀掉运行状态的进程,所以它会杀掉睡眠中的进程,此时这个进程被杀掉了。这时磁盘没有将数据写入成功,后面还有进程需要向磁盘写数据,此时磁盘想给进程返回没有成功时,进程被杀掉了,磁盘只好将数据丢弃掉做后面的工作,进程也不知道是否写入成功。如果这是具体的银行10万条存款记录,这就是一次重大事故。
    因此,防止向磁盘写入重要数据时进程被终止掉,就有一个深度睡眠状态 D,深度睡眠状态下的进程是不可以被杀掉的。一般情况下,我们用户要是可以查到D状态,内存就很忙了,也就意味着几乎要宕机。

2.4 停止状态 T

  • T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
    我们先来看看一些信号:
    在这里插入图片描述
    这些数字对应的信号,在Linux内核中其实是宏定义出来的。
    我们以下面的例子来看看,试一下暂停:
    在这里插入图片描述
    编译后运行:
    在这里插入图片描述
    我们发送信号让进程暂停了,此时我们发现,bash提示符在闪烁等待我们输入,一暂停进程就被改为后台进程了,不影响我们其他的操作。这时我们想要进程再运行起来,我们做下面的操作:
    在这里插入图片描述
    这很简单,但是我们为什么要将状态设置为停止状态呢?
    当进程访问软件资源的时候,可能暂时不让进程进行访问,就将进程设置为STOP。
    t 状态,是我们使用gdb调试代码时,追踪程序,遇到断点,进程就暂停了。
    在这里插入图片描述

这里我们能看到,当我们打了断点后,去运行程序,走到断点处状态变成了t,t表示tracing追踪的意思。
所以,不管是 T/t 都是阻塞状态,这里没有等待硬件资源,而是等待用户的指令,这就叫做 等待软件条件就绪。 因此在具体的os中这些都叫做阻塞状态。

2.5 僵尸状态 Z 与 死亡状态 X

  • X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
  • Z 僵尸状态(zombie):一个比较特殊的状态。当进程退出并且父进程/OS(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程(父进程要知道子进程把任务完成的怎么样)。
  • 僵死进程会以终止状态保持在进程表(PCB)中,并且会一直在等待父进程读取退出状态代码。
  • 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。 如果不及时回收,就会造成内存泄漏(字段会申请资源)。
    我们写一段C语言代码来验证一下 Z 状态,我们父进程不回收子进程:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main()
{pid_t id = fork();if(id < 0) return 1;else if(id == 0){// childint cnt = 5;while(cnt){printf("I am child, run times: %d\n", cnt--);sleep(1);}printf("I am child, dead: %d\n", cnt--);exit(2);}else                                                    {// fatherwhile(1){printf("I am father, running any time!\n");sleep(1);}// 回收操作}return 0;
}

在这里插入图片描述
父进程没有回收子进程,子进程从S状态变为Z状态,defunct就是死者,死亡的意思。
僵尸进程的危害:

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

孤儿进程

刚我们讲的是子进程先退出,父进程不回收,导致子进程僵尸状态,那如果子进程不退出,而父进程先退出呢?
我们写一段这样的C语言代码来看看:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main()
{pid_t id = fork();if(id < 0) return 1;else if(id == 0){// childwhile(1){printf("I am child ...\n");sleep(1);}}else                                                    {// fatherint cnt = 5;while(cnt){printf("I am father, run times: %d\n", cnt--);sleep(1);}printf("I am father, dead: %d\n", cnt--);exit(2);// 回收操作}return 0;
}

在这里插入图片描述
当父进程退出时,是由bash回收的,但是子进程是要被父进程回收的,但是父进程先退出了,子进程要被领养,变成孤儿进程。
一般孤儿进程是要被1号进程领养,如果不领养就无法回收,导致内存泄漏。
那1号进程是谁呢?我们查一下:
在这里插入图片描述
这里一号进程叫做systemd,它其实就是操作系统。

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

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

相关文章

智慧食堂管理方式,究竟改变了什么?

随着科技的迅速发展&#xff0c;餐饮业也在不断地迎来新的挑战和机遇。为了提升食堂管理效率、改善用户体验以及提高收益&#xff0c;许多食堂纷纷引入智慧收银系统。 客户案例 企业食堂改革 石家庄某大型企业食堂由于员工数量庞大&#xff0c;传统的收银方式难以满足快速就餐…

大话 JavaScript(Speaking JavaScript):第二十一章到第二十五章

第二十一章&#xff1a;数学 原文&#xff1a;21. Math 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 Math对象用作多个数学函数的命名空间。本章提供了一个概述。 数学属性 Math的属性如下&#xff1a; Math.E 欧拉常数&#xff08;e&#xff09; Math.LN2 2 …

Verilog 和 System Verilog 的区别

当谈到VLSI设计和数字电路建模时&#xff0c;verilog和system verilog是两种常用的硬件描述语言。这些 HDL 在 VLSI 设计中用于描述电子电路的行为和结构。它们都广泛应用于半导体行业来设计和实现集成电路&#xff08;IC&#xff09;。 它们是设计和模拟复杂数字系统的强大工具…

解决:ModuleNotFoundError: No module named ‘dbutils’

解决&#xff1a;ModuleNotFoundError: No module named ‘dbutils’ 文章目录 解决&#xff1a;ModuleNotFoundError: No module named dbutils背景报错问题报错翻译报错位置代码报错原因解决方法方法一&#xff0c;直接安装方法二&#xff0c;手动下载安装方法三&#xff0c;…

盈利之道:下单前的必问之问

投资者在过去的交易经历中&#xff0c;通常都会面临所谓的“交易低谷”。交易低谷是指在交易过程中难以实现盈利或可能导致进一步亏损的阶段。这种面临损失或没有盈利的时期可能发生在任何人身上&#xff0c;无论是由于市场变化、投资者策略调整还是其他原因。为了应对这种情况…

Hibernate实战之操作MySQL数据库(2024-1-8)

Hibernate实战之操作MySQL数据库 2024.1.8 前提环境&#xff08;JavaMySQLNavicatVS Code&#xff09;1、Hibernate简介1.1 了解HQL 2、MySQL数据库建表2.1 编写SQL脚本2.2 MySQL执行脚本 3、Java操作MySQL实例&#xff08;Hibernate&#xff09;3.1 准备依赖的第三方jar包3.2 …

与听力学相关的职业都有哪些?怎么选择?

随着年龄的增长&#xff0c;每个人都可能面临听觉障碍的困惑。听力学领域专注于患者的耳朵问题&#xff0c;包括听力损失和平衡障碍。听力学职业是为患者提供听觉健康管理服务的职业&#xff0c;专注于他们耳朵的听力和平衡甚至言语相关需求。为患者进行听功能检查、测试、诊疗…

代码随想录算法训练营Day17|110.平衡二叉树、257. 二叉树的所有路径、 404.左叶子之和

文章目录 一、110.平衡二叉树1.递归法 二、257. 二叉树的所有路径1. 递归法 三、 404.左叶子之和1.迭代法 一、110.平衡二叉树 题目描述&#xff1a; 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a;一个二…

C++ Primer 6.2参数传递 知识点+练习题

C Primer 6.2参数传递 知识点练习题 指针形参使用引用拷贝Const 形参实参尽量使用常量引用数组形参数组引用形参传递多维数组向main函数传参数含有可变形参的函数练习题待更新 指针形参 void reset(int *p) {*p0;//p指向的整型对象变为0p0;//只是对形参改变p&#xff0c;使其为…

【Git】查看凭据管理器的账号信息,并删除账号,解决首次认证登录失败后无法重新登录的问题

欢迎来到《小5讲堂》 大家好&#xff0c;我是全栈小5。 这是是《代码管理工具》序列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识点的…

性能测试分析案例-定位内核线程CPU利用率太高

环境准备 预先安装 docker、perf、hping3、curl 等工具&#xff0c;如 apt install docker.io linux-tools-common hping3 操作和分析 Linux 在启动过程中&#xff0c;有三个特殊的进程&#xff0c;也就是 PID 号最小的三个进程。 0 号进程为 idle 进程&#xff0c;这也是系…

Windows 项目从0到1的部署

目录 一. 安装jdk 1.1 安装jdk 1.2 配置jdk的环境配置jdk 1.3 配置成功 二. 配置tomcat 2.1 启动tomcat 2.2 防火墙设置 三. 安装MySQL 3.1 安装步骤 3.2 内部连接 3.3 外部连接 四. 部署项目 4.1 项目部署 4.2 修改mysql的用户密码 一. 安装jdk 这里给大家准备好了jdk和…

2024.1.8 Day04_SparkCore_homeWork

目录 1. 简述Spark持久化中缓存和checkpoint检查点的区别 2 . 如何使用缓存和检查点? 3 . 代码题 浏览器Nginx案例 先进行数据清洗,做后续需求用 1、需求一&#xff1a;点击最多的前10个网站域名 2、需求二&#xff1a;用户最喜欢点击的页面排序TOP10 3、需求三&#x…

一卡通水控电控开发踩过的坑

最近在做一个项目&#xff0c;是对接一卡通设备的。我一开始只拿到设备和3个文档开局。不知道从哪下手。一步一步踩坑过来。踩了很多没有必要的坑&#xff0c;写出来给有用的人吧。 读卡器怎么用&#xff1f; 有个读卡器&#xff0c;一开始什么软件也不提供。我都不知道是干嘛…

Jupyter Notebook

2017年左右在大学里都听说过Jupyter Notebook&#xff0c;并且也安装用了一段时间&#xff0c;后来不知道什么原因没有用了。估计是那时候写代码的时候多一些&#xff0c;因为它可以直接写代码并运行结果&#xff0c;现在不怎么写代码了。 介绍 后缀名为.ipynb的json格式文件…

《YOLO算法:基础+进阶+改进》报错解决 专栏答疑

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。《YOLO算法&#xff1a;基础进阶改进》专栏上线后&#xff0c;部分同学在学习过程中提出了一些问题&#xff0c;笔者相信这些问题其他同学也有可能遇到。为了让大家可以更好地学习本专栏内容&#xff0c;笔者特意推出了该篇…

SpringBoot集成Camunda

一&#xff1a;SpringBoot集成 1.1&#xff1a;pom.xml 因camunda集成SpringBoot对SpringBoot的版本和JDK的版本都有一定的要求&#xff0c;所以这里贴个完整的依赖。可以去官网找每个SpringBoot的版本对应的camunda版本。 <?xml version"1.0" encoding"…

前端入门教程:学完即可单独完成前端项目

目录 目录 1.HTML: 1.1概念 1.2结构 1.3常见的标签使用分类&#xff1a; 2.CSS: 2.1概念 2.2样式实践&#xff1a; 以下的举例都来自于博客&#xff1a; 2.3css选择器&#xff1a; 什么是css选择器&#xff1a; 举例如下&#xff1a; 2.4Demo 3.JavaScript&#…

算法34:贴纸拼词(力扣691题)

题目&#xff1a; 我们有 n 种不同的贴纸。每个贴纸上都有一个小写的英文单词。 您想要拼写出给定的字符串 target &#xff0c;方法是从收集的贴纸中切割单个字母并重新排列它们。如果你愿意&#xff0c;你可以多次使用每个贴纸&#xff0c;每个贴纸的数量是无限的。 返回你…

vivado IP Revision Control

2020.2 只需要git 管理 prj.xpr 和 prj.srcs/ https://china.xilinx.com/video/hardware/ip-revision-control.html https://www.xilinx.com/video/hardware/vivado-design-suite-revision-control.html