【Linux】进程状态

news2024/11/15 7:58:38

文章目录

  • 1. 阻塞
    • 1. 举例
    • 2. 为什么要阻塞?
    • 3.操作系统层面上如何理解进程等待某种资源就绪呢?
      • 资源
      • 进程
    • 4. 总结
  • 2.挂起
  • 3.Linux进程状态
    • 1. R状态
      • 进程只要是R状态,就一定是在CPU运行吗?
      • 证明当前进程运行状态
        • 生成程序
        • 查看进程
    • 2. S休眠状态——可中断休眠
    • 3.D休眠状态 ——不可中断休眠
    • 4.T状态——暂停状态
      • 使用kill命令,向指定的进程发信号
      • 暂停进程
      • 继续进程
      • 带加号的问题
    • 5. X状态(死亡状态)&&Z状态(僵尸状态)
      • 查看当前进程退出码
      • 对于Z状态的理解
        • 举例
      • 验证Z状态
      • 僵尸状态危害

1. 阻塞

进程因为等待某种条件就绪,而导致的一种不推进的状态

1. 举例

  • 有时候电脑卡,是因为开启了太多软件,为什么启动太多程序会卡呢?
  • 启动了太多的程序相当于启动了太多的进程,操作系统在用你的cpu调度时,调度不过来了,当前正在调度的在运行,没有调度的相当于卡了
  • 阻塞就是进程卡住了

2. 为什么要阻塞?

  • 进程要通过等待的方式,等具体的资源被别人使用完成后,再被自己使用
  • 阻塞:进程等待某种资源就绪的过程
  • 以硬件为例,资源可以看作磁盘、网卡、显卡等外设,
    比如去银行存钱,存钱申请的单子没了,直接去存,工作人员就会说因为存钱的单子没有就绪所以不能存,再去等一会,等有单子了再来存
  • 没有继续执行存钱的行为,当前所处状态为阻塞状态

3.操作系统层面上如何理解进程等待某种资源就绪呢?

资源

操作系统对于磁盘、网卡、显卡等 资源通过 先描述,在组织进行管理,把设备用结构体描述起来,再用链表组织起来
管理的本质具体解释点击这里

进程

存在大量的进程,操作系统要进行管理,也要先描述,在组织,就存在了大量的task_struct的结构体,每一个进程都是由task_struct定义出来的对象
进程组成的理解点击这里
在这里插入图片描述

  • 将dev结构体内添加一个队列指针,若进程需要在设备资源等待,则把task_struct链接到设备资源队列的尾部

4. 总结

阻塞:阻塞就是不被调度
一定是因为当前进程等待某种资源就绪
一定是进程task_struct结构体需要在某种操作系统管理的资源下进行排队

2.挂起

在这里插入图片描述

  • 当进程被CPU调度时进行下载,由于网断了,导致下载终止,从而使进程链接到网卡设备队列的尾部,造成阻塞
    从而使CPU调用其他进程

在这里插入图片描述

  • 若系统中内存的资源特别紧张,把占有内存的并且闲置的数据和代码,交换到磁盘当中,把内存中这部分的代码和数据释放,当该进程等待的资源就绪时,再把存入磁盘的数据和代码换入内存中,并把进程放入CPU中运行
  • 把代码和数据暂时性由操作系统交换到磁盘时,此时的进程称之为挂起状态

3.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 */
}; 
  • Linux源码当中进程所对应的状态

struct task_struct
{
int status;//0代表R状态  1代表s状态 4代表T状态
//....
}

task_struct 是一个结构体,内部会包含各种属性,就有状态,通过0、1、2等数字找到对应的进程状态

1. R状态

进程只要是R状态,就一定是在CPU运行吗?

不一定

在这里插入图片描述

  • 每个进程当中有自己的运行队列,只要该进程在队列中进行排队,运行的进程就会在运行的队列中排队,CPU调度进程时,从队列中挑选指定的进程运行就可以了,这种运行状态就叫做R状态

  • R状态不直接代表进程在运行,代表该进程在运行队列中排队

证明当前进程运行状态

生成程序

创建makefile并输入如下内容

   1 mytest:test.c//nakefile
  2   gcc -o mytest test.c 
  3 .PHONY:clean 
  4 clean:
  5  rm -f mytest  


创建test.c并输入如下内容

#include<stdio.h>//test.c
  2 int main()
  3 {
  4   while(1)
  5   {
  6     printf("我在运行吗\n");                                                                                                                                            
  7   }                                                                                                                         
  8   return 0;                                                                                                                 
  9 }                                                                                                                               

[yzq@VM-8-8-centos my]$ make
gcc -o mytest test.c 
[yzq@VM-8-8-centos my]$ ./mytest

make产生可执行程序mytest,./mytest执行可执行程序

查看进程

赋值SSH渠道生成终端2
在保证终端1中的mytest运行的情况下,在终端2中输入指令
ps axj | head -1 && ps axj | grep mytest | grep -v grep

创建终端的方法及指令具体含义点击这里

[yzq@VM-8-8-centos my]$ ps axj | head -1 && ps axj | grep mytest | grep -v grep
  PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
25615 30533 30533 25615 pts/0    30533 S+    1002   0:00 ./mytest

发现此时进程状态为S+ (+号后面会说)
S称为休眠状态,不是R状态


test.c代码修改如下

 #include<stdio.h>//test.c
  2 int main()
  3 {
  4   while(1)
  5   {
  6    // printf("我在运行吗\n");                                                                                                                                        
  7   }                   
  8   return 0;           
  9 }                     
       

在保证终端1中的mytest运行的情况下,在终端2中再次输入指令ps axj | head -1 && ps axj | grep mytest | grep -v grep

[yzq@VM-8-8-centos my]$ ps axj | head -1 && ps axj | grep mytest | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
25615 31695 31695 25615 pts/0    31695 R+    1002   0:10 ./mytest

  • 发现进程状态由S+变为R+
  • printf循环打印,就代表要频繁访问显示器设备,循环中的printf本质就是向外设打印消息,当CPU执行printf代码时,频繁打印外设不一定就绪,进程可能在外设中排队,等资源就绪时,再把进程放入CPU上把结果写入外设中
  • 说明第一次查到的S状态是阻塞状态的一种,是以休眠状态进行阻塞的

2. S休眠状态——可中断休眠

本质是一种阻塞状态

修改test.c代码如下

 1 #include<stdio.h>
  2 int main()
  3 {
  4   while(1)
  5   {
  6    int b=0;
  7    scanf("%d",&b);
  8    printf("%d\n",b);
  9   }                                                                                                                                                                  
 10   return 0;                                                                                                                
 11 }     
  • ./mytest运行,并输入10 10

在保证终端1中的mytest运行的情况下,在终端2中再次输入指令
ps axj | head -1 && ps axj | grep mytest | grep -v grep

[yzq@VM-8-8-centos my]$  ps axj | head -1 && ps axj | grep mytest | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
25615  5793  5793 25615 pts/0     5793 S+    1002   0:00 ./mytest

  • 进程状态为S,进程没有被调度,等键盘资源 即在键盘中输入数据

[yzq@VM-8-8-centos my]$ ./mytest
10
10
^C//可以被终止

  • 在终端1中ctrl c,终止mytest运行,S状态被终止

3.D休眠状态 ——不可中断休眠

想要往磁盘写入100MB的数据,由于磁盘写入数据很慢,所以进程把自己设置成阻塞状态,若内存资源特别紧张,操作系统就想要把这个阻塞状态的进程干掉,可是此时磁盘依旧还在写入数据,这样做就会使磁盘写入数据失败,最终就会使100MB的数据丢失

  • 若该进程的休眠状态为D状态,使操作系统无法干掉进程,就能解决这个问题

4.T状态——暂停状态

使用kill命令,向指定的进程发信号

[yzq@VM-8-8-centos my]$ 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

  • 9号信号SIGKILL 表示干掉 进程
  • 18号信号 SIGCONT 表示让当前进程继续运行
  • 19号信号 SIGSTOP 表示暂停一个进程

暂停进程

test.c内容如下

1 #include<stdio.h>
#include<unistd.h>
  2 int main()
  3 {
  4   int count=0;
  5   while(1)
  6   {                                                                                                                                                                  
  7    printf("还在运行吗:%d\n",count++);
       sleep(1);
  8   }                                  
  9   return 0;
 10 }          



保证在保证终端1中的mytest运行的情况下,在终端2中再次输入指令ps axj | head -1 && ps axj | grep mytest | grep -v grep 并输入 kill-19+PID值,终端1自动停止运行

在这里插入图片描述


[yzq@VM-8-8-centos my]$ ps axj | head -1 && ps axj | grep mytest | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
25615 14791 14791 25615 pts/0    14791 S+    1002   0:00 ./mytest

再次在终端2中查询进程,发现进程状态由S+变为T

继续进程

若想让进程继续运行,在终端2中使用 kill -18 +PID值
在这里插入图片描述

带加号的问题

yzq@VM-8-8-centos my]$ ps axj | head -1 && ps axj | grep mytest | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
25615 14791 14791 25615 pts/0    25615 S     1002   0:00 ./mytest

  • 在暂停进程,又继续进程后,当前进程状态 为S,不带加号了
  • 在终端1使用ctrl c,程序不停止了

  • 进程状态带+,进程是在前台运行的,可以使用ctrl c 终止

  • 进程状态不带+,进程是在后台运行的,可以正常执行shell指令,但在后台继续还会执行自己的代码

  • 此时若想终止进程,使用 kill -9 +PID值 干掉进程

5. X状态(死亡状态)&&Z状态(僵尸状态)

  • X死亡状态只是一个返回状态,你不会在任务列表里看到这个状态,所以这里这是举例时提及,但不会验证
  • 我们创建进程,是为了进程帮我们办事,同时也关心结果,而main函数的返回值是进程的退出码

查看当前进程退出码

用于判定进程结果是否正确 echo $?

修改test.c的内容如下

include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   int count=2;
  6   if(count==2)
  7   {
  8     return 0;
  9   }
 10   else 
 11   {
 12     return 4;
 13   }                                                                            
 14 }
~


使用make生成可执行程序mytest,./mytest执行可执行程序

[yzq@VM-8-8-centos my]$ make
gcc -o mytest test.c 
[yzq@VM-8-8-centos my]$ ./mytest
[yzq@VM-8-8-centos my]$ echo $?
0

  • 说明mytest进程的退出码是0,进程结果正确

对于Z状态的理解

如果一个进程退出了,立马X状态,立马退出,你作为父进程,有没有机会拿到退出结果呢?

  • linux当进程退出的时候,一般进程不会立即彻底退出,而是要维持一个状态叫做Z状态,也叫做僵尸状态
  • 方便后续父进程读取子进程退出的退出结果

如何让我们看到僵尸状态呢?

  • 子进程退出,但是不要回收子进程

举例

  • 假设你在某一天看到路上有一个人躺着,你报了警,警察来了后,先封锁现场,再来人确认躺者是否死亡,法医确认这个人的死因,然后通知家属等一系列事情才能进行
  • 被120、法医检查时,这个人所处的状态就叫僵尸状态
  • 为了方便别人从他的残留信息中甄别他死亡的原因是什么

验证Z状态

修改test.c内容如下

#include<stdio.h>
    2 #include<unistd.h>
    3 int main()
    4 {
    5   pid_t id=fork();
    6   if(id==0)
    7   {
    8     //子进程
    9     while(1)
   10     {
   11       printf("我是子进程,我在运行,pid:%d,ppid:%d",getpid(),getppid());
   12       sleep(1);
   13     }
   14   }
   15   else if(id>0)
   16   {
   17     //父进程
   18     while(1)
   19     {
   20       printf("我是父进程,我在运行,pid:%d,ppid:%d",getpid(),getppid());
   21       sleep(1);
   22   }                                                                          
   23   }
    }


保证在保证终端1中的mytest运行的情况下,在终端2中再次输入指令ps axj | head -1 && ps axj | grep mytest | grep -v grep

[yzq@VM-8-8-centos my]$ ps axj | head -1 && ps axj | grep mytest | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
25615 18251 18251 25615 pts/0    18251 S+    1002   0:00 ./mytest
18251 18252 18251 25615 pts/0    18251 S+    1002   0:00 ./mytest
[yzq@VM-8-8-centos my]$ kill -9 18252
[yzq@VM-8-8-centos my]$ ps axj | head -1 && ps axj | grep mytest | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
25615 18251 18251 25615 pts/0    18251 S+    1002   0:00 ./mytest
18251 18252 18251 25615 pts/0    18251 Z+    1002   0:00 [mytest] <defunct>

  • 当父子进程都运行时,两者进程状态都为S+
  • 当使用 kill - 9 +PID值将子进程干掉后,再次使用指令查询进程,发现子进程为僵尸状态,父进程为S+

僵尸状态危害

  • 在父子进程中,若父进程一直不读取,子进程就会处于Z状态
  • 在父子进程中,若子进程一直处于僵尸状态(即退出子进程,但不回收子进程),就会在内存中一直保留该进程
  • 若父进程创建多个子进程,就是不回收,就会造成内存资源的浪费

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

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

相关文章

New和Malloc的使用及其差异

1&#xff0c;new的使用关于new的定义&#xff1a;new其实就是告诉计算机开辟一段新的空间&#xff0c;但是和一般的声明不同的是&#xff0c;new开辟的空间在堆上&#xff0c;而一般声明的变量存放在栈上。通常来说&#xff0c;当在局部函数中new出一段新的空间&#xff0c;该…

Go项目(三)

文章目录用户微服务表结构查表web 服务跨域问题图形验证码短信用户注册服务中心注册 grpc 服务动态获取端口负载均衡配置中心启动项目小结用户微服务 作为系统的第一个微服务&#xff0c;开发的技术点前面已经了解了一遍&#xff0c;虽有待补充&#xff0c;但急需实战这里主要…

pytorch离线快速安装

1.pytorch官网查看cuda版本对应的torch和torchvisionde 版本(ncvv -V&#xff0c;nvidia-sim查看cuda对应的版本) 2.离线下载对应版本&#xff0c;网址https://download.pytorch.org/whl/torch_stable.html 我下载的&#xff1a; cu113/torch-1.12.0%2Bcu113-cp37-cp37m-win_…

基于python的一款数据处理工具pandas

在python处理数据的时候&#xff0c;都免不了用pandas做数据处理。在数据处理时&#xff0c;都免不了用数据筛选来提取自己想要的数据&#xff0c;咱们今天就讲讲pandas的条件筛选。安装库建议做数据分析的酱友们安装anaconda3&#xff0c;这个包几乎包括了数据分析用的所需要的…

【博客623】Prometheus一条告警的触发流程与等待时间

Prometheus一条告警的触发流程与等待时间 1、与告警等待时间相关的参数 prometheus.yml global:# 数据采集间隔scrape_interval: 15s # 评估告警周期evaluation_interval: 15s # 数据采集超时时间默认10s# scrape_timeoutalertmanager.yml # route标记&#xff1a;告警…

Python urllib

Python urllib Python urllib 库用于操作网页 URL&#xff0c;并对网页的内容进行抓取处理。 本文主要介绍 Python3 的 urllib。 urllib 包 包含以下几个模块&#xff1a; urllib.request - 打开和读取 URL。urllib.error - 包含 urllib.request 抛出的异常。urllib.parse …

剑指Offer专项突击版题解八

71.按权重生成随机数 思考&#xff1a;说到平均的生成随机数&#xff0c;想到了水塘抽样法和彩票调度法。 水塘抽样算法适合于样本不确定&#xff0c;乃至于是变化的&#xff0c;每个样本的概率是一样的。 // 样本nums[],每个元素的被抽到的概率是一样的 index : 0 for i : 1;…

Kubernetes03:kubernetes 功能和架构

2.1 概述 Kubernetes 是一个轻便的和可扩展的开源平台&#xff0c;用于管理容器化应用和服务。通过 Kubernetes 能够进行应用的自动化部署和扩缩容。在 Kubernetes 中&#xff0c;会将组成应用的容 器组合成一个逻辑单元以更易管理和发现。Kubernetes 积累了作为 Google 生产环…

时序预测 | Python实现TCN时间卷积神经网络时间序列预测

时序预测 | Python实现TCN时间卷积神经网络时间序列预测 目录 时序预测 | Python实现TCN时间卷积神经网络时间序列预测预测效果基本介绍环境准备模型描述程序设计学习小结参考资料预测效果 基本介绍 递归神经网络 (RNN),尤其是 LSTM,非常适合时间序列处理。 作为研究相关技术…

生成模型技术发展过程

生成模型生成模型和判别模型的差异生成模型的目标是在给定了数据集D&#xff0c;并且假设这个数据集的底层分布(underlying distribution)是Pdata&#xff0c;我们希望够近似出这个数据分布。如果我们能够学习到一个好的生成模型&#xff0c;我们就能用这个生成模型为下游任务做…

【项目立项管理】

项目立项管理 很杂&#xff0c;可以根据左边的列表查看自己不会的 。。。 立项管理主要是解决项目的组织战略符合性问题 开发所需的成本和资源属于经济可行性 承建方组织资源和项目的匹配程度 内部立项目的&#xff1a; 为项目进行资源分配&#xff0c;确定项目绩效目标&am…

字节二面:10Wqps超高流量系统,如何设计?

超高流量系统设计思路 前言 在40岁老架构师 尼恩的**读者交流群(50)**中&#xff0c;大流量、高并发的面试题是一个非常、非常高频的交流话题。最近&#xff0c;有小伙伴面试字节时&#xff0c;遇到一个面试题&#xff1a; 10Wqps超高流量系统&#xff0c;该如何设计&#xf…

湿度敏感性等级(MSL)

趁着周末得空&#xff0c;也有意愿&#xff0c;赶紧把之前一直想写的这个主题完成了。 湿度敏感性等级&#xff0c;相信大部分人还是比较陌生的。 湿度敏感性等级&#xff1a;MSL&#xff0c;Moisture sensitivity level 之所以有这个等级&#xff0c;大概是因为以下原因&a…

软考高级-信息系统管理师之进度管理(最新版)

项目进度管理 项目进度管理1概述2项目进度管理过程2.1规划进度管理1、规划项目进度管理目的2、规划进度管理:输入3、规划进度管理:输出2.2定义活动1、为了更好地规划项目2、定义活动过程就是3、定义活动:输入4、定义活动:输出2.3排列活动顺序1、排列活动顺序2、排列活动顺序:输…

19 顺序存储二叉树

文章目录1 顺序存储二叉树的概念1 顺序存储二叉树的概念 从数据存储来看&#xff0c;数组存储方式和树的存储方式可以相互转换&#xff0c;即数组可以转换成树&#xff0c;树也可以转换成数组&#xff0c;看右面的示意图。 要求: 1) 右图的二叉树的结点&#xff0c;要求以数…

Git常用命令以及如何在IDEA中使用Git

前言Git是一个分布式版本控制工具&#xff0c;主要用于管理开发过程中的源代码文件&#xff08;Java类、xml文件、html页面等&#xff09;。Git在管理文件过程中会记录日志&#xff0c;方便回退到历史版本&#xff1b;Git存在分支的概念&#xff0c;一个项目可以有多个分支&…

linux014之进程和服务管理

linux中的进程管理&#xff1a; 查看进程命令&#xff1a; ps &#xff1a;查看应用级别的进程 ps -e&#xff1a; 查看系统应用级的进程 ps -ef &#xff1a;显示进程的全部信息(这个命令经常用) ps -ef|grep 关键字&#xff1a; 查看带有关键字的进程 关闭进程命令&#xff1…

win11+pytorch1.7.0+python3.8(也可以是python3.7)+cuda11.0

win11pytorch1.7.0python3.8cuda11.0写在最前面一. 软件配备二. 创建虚拟环境2.1 创建环境名称&#xff0c;并选择‘y’2.2.进入虚拟环境三. 安装pytorch四. 安装虚拟环境下的notebook4.1 安装ipykernel&#xff0c;并选择‘y’&#xff0c;直至安装完成4.2 将环境名注册到note…

安全—09day

XSS1. XSS的原理2. Xss漏洞分类2.1 反射性xss2.2 存储型XSS2.3 基于DOM的 XSS2.4 XSS漏洞的危害3. XSS的各种bypass技巧4. 从 XSS Payload 学习浏览器解码5. 浏览器解析机制5.1 HTML中有五类元素&#xff1a;5.2 五类元素的区别1. XSS的原理 恶意攻击者往Web页面里插入恶意Scr…

AcWing:4861. 构造数列、4862. 浇花(C++)

目录 4861. 构造数列 问题描述&#xff1a; 实现代码&#xff1a; 4862. 浇花 问题描述&#xff1a; 实现代码&#xff1a; 4861. 构造数列 问题描述&#xff1a; 我们规定如果一个正整数满足除最高位外其它所有数位均为 00&#xff0c;则称该正整数为圆数。 例如&…