Linux的进程状态


前言

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态,一个进程有几个状态(在Linux内核里,进程有时候也叫做任务)
下面是kernel源代码:

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

提示:以下是本篇文章正文内容,下面案例可供参考

一、R运行状态(running)

R运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。

在这里插入图片描述
只要你的代码从磁盘中加载到内存,内存随即会生成一个属于这个代码的PCB进程控制块,并且加载到CPU的运行队列中,只要PCB还在CPU运行队列中,就属于R状态,并不是占有CPU的时候才是R状态。
在这里插入图片描述
在这里插入图片描述

#include <stdio.h>                                                          
#include <unistd.h>
int main()
{
	 pid_t id = fork();
  	 if(id == 0)
  	 {
 	    while(1)
 	    {}
 	 }
	 else if(id < 0)
 	 {
 	   perror("fork faile");
 	 }
 	 else
 	 {
 	   while(1)
 	   {}
	 }
	 return 0;
}


S睡眠状态(sleeping)

S睡眠状态(sleeping):意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))这里的睡眠是可以被叫醒的。在这里插入图片描述
当一个进程需要访问外设时,由于外设的速度对于CPU来说太慢了,CPU需要等待吗?实际CPU是不等待的,把PCB的进程块置为S睡眠状态,等待进程访问外设完成后,再重新放到队列中等待运行
在这里插入图片描述
在这里插入图片描述
虽然显示器还在不断的输出,但查询进程状态已经显示睡眠了,证明CPU已经做完了他的活,现在轮到进程输出结果到屏幕上了,状态已经改为S+了,带+号代表是前台进程,不带+号的是后台进程。

#include <stdio.h>                                                          
#include <unistd.h>
 
int main()
{
  pid_t id = fork();

  if(id == 0)
   {
     while(1)
     {
       printf("i am child my pid:%d,my parent ppid:%d\n",getpid(),getppid());
       sleep(1);
     }
   }
   else if(id < 0)
   {
     perror("fork faile");
   }
   else
   {
     while(1)
     {
       printf("i am parent my pid:%d\n",getpid());
       sleep(1);
     }
   }
   return 0;
 }       

还有一种情况是,进程阻塞挂起状态,由于进程短期内不需要使用的话,操作系统会把这个进程的相关数据,保存在磁盘上,为其他进程腾出空间,如果这个进程需要运行时,再把他抱回到CPU运行队列。


三.D磁盘休眠状态(Disk sleep)

D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
出现这种情况,无法被操作系统杀死,只能通过断电,或等进程自己醒来解决。


四.T停止状态(stopped)

T停止状态(stopped):可以通过发送SIGSTOP信号给进程来停止(T)进程。这个被暂停的进程可以通过发送SIGCONT信号让进程继续运行。
在这里插入图片描述

在这里插入图片描述
这里我们用的是 kill -19 28406 命令,让一个进程暂停,kill+ 命令,加该进程的pid,即可控制该进程。
在这里插入图片描述
在这里插入图片描述
这里我们用的是 kill -18 28406 命令,让一个进程暂停,kill+ 命令,加该进程的pid,即可控制该进程,需要注意的是,继续后的进程,已经转为后台进程了,我们按control+c已经无法结束该进程了,需要用kill -9 28406来杀死这个进程
在这里插入图片描述
在这里插入图片描述关于kill命令的使用方式可观看点击链接


五.t追踪停止状态(tracing stop)

T和t状态很类似,都是表示进程暂停下来。
而t状态相当于在T之上多了一层保护,处于t状态的进程不能响应kill 命令的SIGCONT信号而被唤醒。
在这里插入图片描述
在这里插入图片描述
处于gdb调试打断点的情况下,就是小t状态。


六.x死亡状态(dead)

X(dead)是死亡状态,这个状态是一个返回状态,所以我们通过指令来查看的时候是不会看到这个状态的。进程在退出过程中也可能不会保留它的task_struct。此时,进程将被置于X退出状态,这意味着接下来的代码立即就会将该进程彻底释放。X状态是非常短暂的,几乎不可能通过ps命令捕捉到。命好的可以去尝试一下捕捉一下。


七.Z僵尸状态(zombie)

僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵死(尸)进程。
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
在这里插入图片描述
在这里插入图片描述
每一个进程就相当于一个任务,我们需要知道这个任务完成了没有,还是有什么异常状态,所以每个任务完成后,需要等待父进程去读取进程完结的代码,如果这时候父进程没有去读取退出代码的话,就会产生这个进程一直占着内存的资源,就会造成内存泄漏,下一期博客讲如何处理。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
  pid_t id = fork();

  if(id == 0)
  {
    while(1)
    {
      printf("i am child my pid:%d,my parent ppid:%d\n",getpid(),getppid());
      sleep(1);
      exit(EXIT_SUCCESS);
    }
  }
  else if(id < 0)
  {
    perror("fork faile");
  }
  else
  {
    while(1)
    {
      printf("i am parent my pid:%d\n",getpid());
      sleep(1);
    }
  }
  return 0;
}


二,孤儿进程

父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?父进程先退出,子进程就称之为“孤儿进程”
孤儿进程被1号init进程领养,当然要有init进程回收喽。
在这里插入图片描述

在这里插入图片描述
如果父进程先于子进程退出的话,子进程会被1号进程领养,也由1号进程进行回收。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
  pid_t id = fork();

  if(id == 0)
  {
    while(1)
    {
      printf("i am child my pid:%d,my parent ppid:%d\n",getpid(),getppid());
      sleep(5);
    }
  }
  else if(id < 0)
  {
    perror("fork faile");
  }
  else
  {
    while(1)
    {
      printf("i am parent my pid:%d\n",getpid());
      sleep(1);
      exit(EXIT_SUCCESS);
    }
  }
  return 0;
}

这里做个说明grep称为全局正则表达式检索工具,我们在使用的时候他也是一个进程,所以会显示出来grep的进程
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值