目录

二.进程状态

        2.1 内核源码中的定义

        2.2 进程状态查看

        2.3 详解各种进程状态

1.R运行状态

2.S休眠状态(阻塞状态)

3.D深度睡眠状态

4.T暂停状态

5.x终止状态

        2.4 Z僵尸状态(zombie)

        2.5 孤儿进程


二.进程状态

        2.1 内核源码中的定义

进程在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):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列 里。

S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠 (interruptible sleep))。

D磁盘休眠状态(Disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的 进程通常会等待IO的结束。

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

X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

        

python ssh判断等待_后端

        2.2 进程状态查看

使用:

ps aux / ps axj      命令

选项

含义

-a

显示终端上的所有进程,包括其他用户的进程

-u

显示进程的详细状态

-x

显示没有控制终端的进程

-j

列出与作业控制相关的信息

此时我们在LInux下输入ps axj 后,系统便会弹出当前各种进程的信息

python ssh判断等待_后端_02

在这里面我们会看到第一行列出了许多参数,下面简单介绍几个,其中:

  • PPID(Process ID)--- 父进程ID
  • PID(Parent Process ID)--- 进程ID
  • PGID(Process Group ID)--- 进程组ID
  • SID(Session ID)--- 会话ID
  • UID(User  ID) --- 用户id
  • STAT:里面的参数对应2.1上表,就是该进程此时的状态

        2.3 详解各种进程状态

1.R运行状态

task_struct 结构体在运行队列中排队,就叫做运行态

(就好比你在食堂排队,同学打电话问你在干嘛,我们一般会回答在吃饭)

我们用while随便写一个死循环,再编译运行,此时这个进程的状态就可以称作R状态

2.S休眠状态(阻塞状态)

系统中存在着各种资源,例如CPU,网卡,磁盘,显卡......等多种设备.

也就决定了系统中存在多种队列,各个进程想要访问同一硬件资源就必须得排队

我们称等待CPU资源就位的进程为运行状态,那么称等待非CPU资源就绪的状态就称为阻塞状态

python ssh判断等待_python ssh判断等待_03

就比如我们常常写的scanf代码, 就是在等待键盘输入的就绪,此时就可以称为S状态

3.D深度睡眠状态

当服务器压力过大的时候,操作系统会通过一定的手段,杀掉一些进程,来起到节省空间的作用!

假设此时存在一个进程正在向磁盘写入数据,但如果此时服务器压力过大,我们希望杀掉这个进程吗?

当然不会!我们肯定不希望重要的数据丢失,这时候我们的系统的就会选择将该进程的状态设置为D状态

此时该状态下的进程无法被系统杀掉,同时也不能被动唤醒,只能等该进程得到磁盘的返回结果(写入成功或失败)后主动醒来,如果计算机存在大量D状态的进程甚至可能无法关机T

4.T暂停状态

想让一个程序处于暂停状态我们可以使用kill命令

python ssh判断等待_python ssh判断等待_04

这里我们用kill -l 列出了kill命令可以发送的所有信号,其中的 18 与 19 就与暂停状态有关

  • kill -19 PID :让PID对应的进程处于停止状态
  • kill -18 PID :让PID对应的处于停止状态的进程恢复运行

应用场景:

当我们在调试代码时,打断点让程序停下来,本质上就是调试器向进程发送信号,让其处于停止状态

5.x终止状态

进程在执行结束后,会短暂进入x状态,等待操作系统回收

实际上由于计算机的高速运转,资源回收非常迅速,该状态瞬时性非常强,一般很难捕捉

        2.4 Z僵尸状态(zombie)

  • 僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面在写到进程控制时会详细讲解) 没有读取到子进程退出的返回代码时就会产生僵尸进程
  • 僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
  • 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

来一个创建维持30秒的僵死进程例子:

python ssh判断等待_子进程_05

编译代码得到程序

python ssh判断等待_父进程_06

此时再编写shell脚本来监控进程

python ssh判断等待_python ssh判断等待_07

之后我们在运行我们的程序后

python ssh判断等待_linux_08

此时再观察编写的监控程序,便可以看到我们新创建的进程

python ssh判断等待_子进程_09

5s后,子进程结束,而父进程还在,且没有读取子进程状态,则子进程成为僵尸进程,状态变为Z

python ssh判断等待_子进程_10

僵尸进程危害:

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

        2.5 孤儿进程

  • 父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?
  • 父进程先退出,子进程就称之为“孤儿进程”
  • 孤儿进程会被1号init进程自动领养,还要由init进程回收,孤儿进程实际上没有什么危害

这里大家可以类比僵尸进程的代码,自行编写观察