Linux中进程的六种状态

目录

R运行状态(running)

S睡眠状态(sleeping)

D磁盘休眠态(Disk sleep)

Z僵尸状态(zombie)

僵尸进程

僵尸进程的危害

T停止状态(stopped)

X死亡状态(dead)

特殊的进程:孤儿进程


 

R运行状态(running)

并不意味着进程一定处在运行中,它表示进程处在运行中或者运行队列里

这和我们平时的理解有所不同,如果想知道其中缘由,需要我们深入理解cpu是如何运行进程的:


准备好运行的进程会链接在一起,形成一个运行队列。

OS会创建一个管理运行队列的结构体,结构体中含有指向进程头部和尾部的指针。

当cpu运行进程时,可以通过结构体的指向,直接获取队列头部的进程。

调度器:相当于一个函数,将运行队列作为参数传进来,就可以找到所有正在排列的所有进程。

**运行态:处于运行队列的进程就叫做处于运行状态。

在运行队列里的含义就是:我已经准备好了,可以随时被调用。

一个进程只要把自己放到CPU上开始运行了,是不是要一直到执行完毕,才把自己放下来?

不是!!!

如果我写一个while(1)死循环,那么在这个循环跑的时候,其他所有进程都不能运行,实际生活的经验告诉我们,这显然是不可能的。

为了防止一个进程在cpu上下不来,每一个进程都有一个叫做时间片的概念。比如 int t =10ms。当跑完时间片上的时间以后,进程就会从cpu上下来,放到队列的尾部。1s内可以跑很多个进程,所以用户看到每个进程都在跑。

在一段时间内,所有进程的代码都会被执行,叫做并发执行。

代码中存在大量的把进程从cpu上放上去和拿下来的动作,这个动作叫做进程切换。

S睡眠状态(sleeping)

表示进程等待某件事件完成,又叫做阻塞状态。这里的睡眠指可中断睡眠。

在学习c语言的过程中,我们都用过scanf函数,当提示我们从键盘输入数据但我们还未输入时,整个程序是不会往下继续进行的,此时这个进程就处于阻塞状态。

 --------------------------------------------------------------------------------------------------------------------------------

在操作系统中绝大多数进程都处于阻塞状态,操作系统内存不足时,会想办法节省出来一些内存资源。

因为在阻塞状态时,进程的数据和二进制代码是用不到的,所以操作系统就将一部分进程的二进制代码放入磁盘中存储,仅仅留下PCB排队。这个过程叫做唤出

当需要用到数据和二进制代码时,再将其加载进内存。这个过程叫做唤入

D磁盘休眠态(Disk sleep)

也叫作不可中断睡眠态(深度睡眠),在这个状态的进程通常会等待IO状态的结束

 都已经有了睡眠状态,为什么还有增加一个不可中断睡眠态?

上述三者只是各司其职,但却造成了数据的缺失,这时设计上的缺陷,所以引入了D状态。

D状态相当于有了一个免死金牌,即使是操作系统也不能杀掉这种状态下的进程。

Z僵尸状态(zombie)

僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。

僵尸进程会以终止状态保持在进程表中,并且一直等待父进程读取状态退出代码。

所以,只要子进程退出,父进程还在运行,但是父进程没有读取子进程状态,子进程进入Z状态

类似当一个人去世以后,必须要等到他的亲属得到通知以后,才能进行下一步的处理。

在进程中,子进程挂掉以后,要将执行结果等一些信息告诉父进程,父进程知道以后,才能被清理。

僵尸进程

代码:

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

int main()
{
    printf("我是一个进程啦,my id is:%d,my parent id:%d\n",getpid(),getppid());
    sleep(2);

    pid_t id =fork();
    if(id == 0){
        int cur=5;

        while(cur){
        cur--;
        printf("我是子进程,pid:%d,ppid:%d\n",getpid(),getppid());
        sleep(1);
      }
    }
    else if(id>0){
        while(1){
         printf("我是父进程,pid:%d,ppid:%d\n",getpid(),getppid());
         sleep(1);
        }   
    }else{

    }

    return 0;
}

运行结果:

僵尸进程的危害

如果父进程一直不读取子进程的退出状态,那么子进程就一直处于Z状态?是的!

维护退出状态本质就是用数据维护,也属于进程的基本信息,存储在task_struct(PCB)中,换句话说,如果Z状态一直不退出,那么PCB一直都要维护?是的!

如果一个父进程有很多个子进程,就是不回收,是不是会造成内存的浪费?是的!

也就是说造成了内存泄漏?是的!

在后续的学习这中会更新避免出现僵尸进程的方法。

T停止状态(stopped)

可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行

X死亡状态(dead)

这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

目前为止,出现的值得关注的进程状态已经全部讲完,下面我们来认识另外一种特殊的进程


孤儿进程

孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

代码:

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

int main()
{
    printf("我是一个进程啦,my id is:%d,my parent id:%d\n",getpid(),getppid());
    sleep(2);


    pid_t id =fork();
    if(id ==0  ){
      while(1){
        printf("我是子进程,pid:%d,ppid:%d\n",getpid(),getppid());
        sleep(1);
      }
    }
    else if(id>0){
        int cur=5;
        while(cur){
          cur--;
          printf("我是父进程,pid:%d,ppid:%d\n",getpid(),getppid());
          sleep(1);
        }   
    }
    else{

    }

    return 0;
}

执行结果:

 注:S+中的+表示在前台运行的意思,在前台运行的可以通过ctrl+c停止,在后台运行的不行,要通过信号,kill -9 PID

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值