• 【liunx】进程的状态


    1.进程的状态

    我们或多或少了解到进程的状态分为:
    运行,新建,就绪,挂起,阻塞,等待,停止,挂机,死亡…

    首先解释一点,进程这么多状态,本质上都是用来满足不同运行场景的。

    接下来我们从两个方面来理解进程的状态

    1.普遍的操作系统层面理解进程的概念

    在这里插入图片描述

    总结:
    1.一个cpu一个运行队列
    2.让进程进队列,本质上是将进程的task_struct结构体对象放在运行队列中
    3.进程pcb在运行队列,就是R,不是这个进程正在运行,才是运行状态

    状态其实是进程内部的属性,放在task_struct,本质是就是int类型的数字来表示不同的状态(假如1:run 2:stop …)。

    我们知道磁盘速度都是很慢的,进程或多或少会访问磁盘,但是磁盘也只有一个,那该怎么办呢?
    只能是等待

    4.不要只以为,你的进程只会等待(占用)cpu资源,你的进程也可能随时随地要外设资源。

    在这里插入图片描述

    cpu发现某个进程需要访问磁盘,就会把该进程从运行队列中剥离,如果这个磁盘现在正由其他进程使用,操作系统就会把该进程放在磁盘的等待队列里(将task_struct对象放在不同队列中),该进程会由运行状态变成阻塞状态。,当磁盘处理完进程,但是等待队列中的进程还是阻塞状态,操作系统会把该进程拿到系统中,把状态改成R(运行状态)再给cpu的运行队列中。

    5.所谓的进程不同的状态,本质是进程在不同的队列中,等待某种资源。

    进程处于阻塞状态,可能不会被立即调度,万一阻塞的进程有很多,内存空间不够了怎么办?
    在这里插入图片描述

    操作系统会把该进程对应的代码和数据暂时保存到磁盘上,pcb还在内存。这样就节省了一部分空间,然后把这一部分空间给别人使用。
    在这里插入图片描述
    此时的进程就处于挂起状态

    将进程的代码和数据,加载或者保存到磁盘叫做内存数据的唤入换出

    阻塞并不一定挂起,挂起一定阻塞。

    进程的状态我们这里就说这么多,主要要知道,1.什么叫做运行;2.什么叫做阻塞;3.什么叫做挂起。

    接下来我们从另一方面来了解进程

    2.Linux是怎么做的(具体的linux操作系统的状态)

    STAT 状态

    #include
       
       int main()
       {
       
           while(1)
           {}
                                                                                                                                                                        
          return 0;
      }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    R+ 运行

    #include
    #include
    
    int main()
    {                                                                                                                                                                   
    	int a=0;
    	while(1)
    	{
    		printf("%d\n",a++);
    		sleep(1);
    	}
      
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    S+ 休眠

    printf会把内容打印到显示器上去,显示器是一个外设,外设特点就是慢,等待显示器就绪,cpu需要花较长的时间。99%都是在等IO就绪,1%再执行打印代码。

    所有进程访问外设行为基本都是S(阻塞状态的一种)

    kill -l  //查看kill命令
    
    • 1

    在这里插入图片描述

    kill -19 编号  //暂停进程
    
    • 1

    在这里插入图片描述

    T 暂停(阻塞的一种)

    kill -18 编号 //继续进程
    
    • 1

    在这里插入图片描述
    这里注意一点,在睡眠的状态是S+,当我暂停进程,又继续进程之后。这个进程状态就变成S了;

    状态后面带+,属于前台进程,在xshell输入任何指令没用,除了用ctrl+c,结束进程。
    状态后面不带+,属于后台进程,在xshell输入指令都有效,使用ctrl+c不能结束进程,只能使用kill -9 杀死进程。

    在这里插入图片描述
    ctrl+c不能杀死后台程序

    在这里插入图片描述
    输入指令还有效

    在这里插入图片描述
    对于后台程序只能通过kill -9 杀死进程。

    D 深度睡眠

    讲个小故事帮助我们理解D状态。

    今天我想让进程帮我向磁盘写个超大份的数据,磁盘答应给我写,那么磁盘就开始写了。写了一会操作系统发现我们电脑变得很卡,操作系统是很聪明的,它去查看,发现这个进程导致电脑变卡,如果不删去这个进程而去删别的进程就会导致其他进程有意见,所以操作系统决定给它删了,过了一会磁盘写数据遇见错误,呼叫进程,但是进程被删了,所以最终导致写入数据失败。当我发现写入数据失败,我问它们三个到底是谁的责任?

    请问是操作系统的责任吗?请问是进程的责任吗?请问是磁盘的责任吗?

    操作系统回答说,不是我的责任,这是我们赋予它的权力,为了保证系统正常运行。
    进程回答说,不是我的责任,我是被操作系统给删掉了。
    磁盘回答说,也不是我的责任,我只负责任写。

    那么为了想把数据写到磁盘里,我只能给这个进程发一个免死金牌,让操作系统不能删掉它。

    像在高级IO的情况,该进程就处于D(深度睡眠),在该状态的进程,无法被操作系统杀掉!只能通过断电,或者进程自己醒来才能解决

    S+ 休眠,属于浅度睡眠可以被终止

    t 也是暂停状态,表示该进程正在被追踪,等待指令,当调试的时候。出现该状态

    在这里插入图片描述

    在这里插入图片描述

    X(dead)死亡状态

    Z(zombie)僵尸状态

    2.僵尸进程

    为什么会有僵尸状态?(感性的认识)
    进程被创建出来,是为了完成任务。
    1.要知道它完成的如何。2.不关系结果。

    Linux是一个你可以不要,但我要给。
    所以进程退出的时候,不能立即释放该进程对应的资源(代码和数据释放掉,PCB保留),保存一段时间,让父进程或者操作系统来进行读取,因什么原因而退出。这段时间内进程处于僵尸状态。

    所谓僵尸状态就是:当进程退出的时候,如果没有对该进程回收,此时进程处于僵尸。

    我们在linux下见见僵尸状态
    具体做法,子进程退出,但是父进程和操作系统没有对其回收------> 创建一个子进程,让父进程不要退出,而且什么都不做,让子进程正常退出即可。

    #include
    #include
    #include
    int main()
    {
        pid_t id=fork();
        if(id == 0)
        {
             //子进程
             int cnt=10;
             while(cnt--)
             {
                 printf("子进程, pid : %d , ppid : %d  ,ret : %d ,cnt=%d\n",getpid(),getppid(),id,cnt);
                 sleep(1);
             }                                                                                                                                                        
             exit(-1);
         }
         else if(id > 0)
         {
     
            //父进程
            while(1)
            {
                 printf("父进程, pid : %d , ppid : %d  ,ret : %d\n",getpid(),getppid(),id);
                 sleep(3);
            }
         }
         return 0;
     }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述
    在这里插入图片描述

    3.孤儿进程

    所谓孤儿进程就是,当父进程先退出,这个子进程会被操作系统(1号进程)领养,这个子进程叫做孤儿进程。

    这里要说明的是:
    1.父进程先退出这种情况一定是存在的。
    2.子进程会被操作系统(1号进程)领养。
    3.那为什么要领养呢?
    如果不领养,那么子进程退出的时候,对应的僵尸便没有人能回收了。造成了资源浪费。
    4.被领养的进程----孤儿进程
    5.如果是前台进程创建的子进程,变成了孤儿,会自动变成后台程序,只能被杀死。

    int main()
    {
        pid_t id=fork();
        if(id > 0)
        {
             //父进程
             int cnt=10;
             while(cnt--)
             {
                 printf("父进程, pid : %d , ppid : %d  ,ret : %d ,cnt=%d\n",getpid(),getppid(),id,cnt);
                 sleep(1);
             }                                                                                                                                                        
             exit(-1);
         }
         else if(id > 0)
         {
     
            //子进程
            while(1)
            {
                 printf("子进程, pid : %d , ppid : %d  ,ret : %d\n",getpid(),getppid(),id);
                 sleep(3);
            }
         }
         return 0;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述
    在这里插入图片描述
    发现当父进程退出,子进程会被操作系统(1号进程领养)。并且子进程由前台程序变成了后台程序,只能被杀死。

    在这里插入图片描述

    关于进程的状态我们就说这么多,喜欢的点赞,评论,收藏+关注。下篇继续了解更多关于进程的知识。

  • 相关阅读:
    2021-08-25-Tomcat服务器与HTTP协议
    周赛372(正难则反、枚举+贪心、异或位运算、离线+单调栈)
    混合App开发模式之「Native+小程序」
    [2022 Google开发者大会] 机器学习-TensorFlow会议记录
    R语言连接 Spark
    APP破解去广告
    进程的概念
    时序预测 | MATLAB实现基于ELM-AdaBoost极限学习机结合AdaBoost时间序列预测
    仙人指路,引而不发,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中New和Make函数的使用背景和区别EP16
    营收、利润双增长,龙湖集团找到多元增长的答案?
  • 原文地址:https://blog.csdn.net/fight_p/article/details/132739280