【Linux进程】进程状态(运行&&阻塞&&挂起)

目录

前言

[1. 进程状态](#1. 进程状态)

[2. 运行状态](#2. 运行状态)

[3. 阻塞状态](#3. 阻塞状态)

[4. 挂起状态](#4. 挂起状态)

[5. Linux中具体的状态](#5. Linux中具体的状态)

总结


前言

在Linux操作系统中,进程状态非常重要,它可以帮助我们了解进程在系统中的运行情况,从而更好地管理和优化系统资源,在Linux系统中,进程可以处于不同的状态,本文我们来聊一聊运行、阻塞、挂起这几状态;

1. 进程状态

在许多教材以及资料当中有许多对进程状态的总结与描述,资料不同它们的描述也各有略同,但总都是一些概念,Linux进程状态具体是什么?本文我们将从底层出发,聊一聊运行、阻塞、挂起这几状态;

温馨提示:如果在本文中某些名称或者内容不太了解,可以先阅读这篇文章:

Linux进程的理解

2. 运行状态

从计算机硬件出发,我们写的代码生成可执行文件都被存储在磁盘当中,想要让程序运行就必须将程序加载到内存当中;

每一个程序(进程)都会有一个属于自己的PCB,通过PCB来进行排队,等待CPU的调度;

为了便于调度管理,操作系统会在内存当中维护一个叫运行队列的结构,所有就绪状态的进程的PCB会被加入到这个队列当中;

CPU在调度执行时就会通过这个运行队列拿到进程的PCB,进而调度执行该进程;

只要进程在这个运行队列当中,它的状态就是运行状态;每个CPU在系统中都会维护一个运行队列;

3. 阻塞状态

了解完运行状态,我们再来聊一聊阻塞状态,阻塞状态是建立在进程被调度执行的基础上;

在CPU执行一个进程时,都可能会或多或少的去访问系统的某些资源,比如:我们使用的scanf,在执行时需要调用键盘(本质就是从键盘中读取数据);

我们不输入,键盘的数据就是没有就绪(进程需要访问的数据没有就绪),此时进程无法继续执行,需要等待数据;

状态又是如何转变的呢?

操作系统和驱动程序它们对硬件进行管理,每个硬件都会有一个属于自己的结构描述,通过指针链接,操作系统通过链表(dev_list)达到对硬件设施的管理;

当进程正在等待某个硬件的资源时,把进程的PCB加入到硬件设备结构描述的等待队列当中,并把PBC的状态设置为阻塞状态;当PCB在这个等待队列中等待数据资源时,这个状态就叫做阻塞状态;

系统资源等待结束之后,操作系统会再次将等待队列中的PCB移入到运行队列当中,并把状态修改为运行状态,等待CPU的执行调度;

4. 挂起状态

了解完阻塞状态,我们来聊一聊挂起状态;挂起全称:阻塞挂起;

挂起是基于阻塞的一种状态;

进程处于阻塞状态时,并且内存不足的情况下就会出现;

针对于这种情况,操作系统会将阻塞进程的代码和数据置换到外设,此时该进程的状态就被称为挂起状态;

阻塞进程的代码和数据一般会存放在磁盘的swap分区,当进程被操作系统调度时,被置换到外设的代码和数据又会重新加载到内存;

拓展补充

一般情况下,swap分区的大小不会太大,大概等于内存的大小,过大的swap分区会导致操作系统过于依赖swap分区,导致效率变低;

5. Linux中具体的状态

说了这么多理论,那么在Linux中进程的状态又是怎样的?

cpp 复制代码
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内核源码对进程状态的定义;它其实并没有像阻塞挂起这样的状态;

我们也可以写一个程序来测试一下:

cpp 复制代码
#include <stdio.h>
#include <unistd.h>

int main()
{
    while(1)
    { 
        printf("hello world! \n");
    }
    return 0;
}

在Linux环境下编译运行,然后使用监控进行观察:

bash 复制代码
while :; do ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep; sleep 1; done
//myprocess是可执行文件的名称

观察到的情况分为两种,大多数是S+,极少数是R+:

主要是因为调用的printf,在输出时需要调用显示器,大多数的时间都是在等待显示器;我们也可以写一个空的死循环执行来观察;

R状态我们都知道是运行状态,S状态是什么?

S(sleeping)休眠状态,这里的睡眠是浅度睡眠,可以对发送的信号做出响应;

这里的 "+" 号是什么意思?

进程被分为前台进程和后台进程,带+号就表示是前台进程;

  • 前台进程:正常使用 ./可执行程序,这种执行方式运行起来就是前台进程,前台进程运行时,无论我们怎么输入指令都无法被执行(Ctrl +c可终止进程)
  • 后台进程:./ 可执行程序 & 这种执行方式运行起来就是后台进程,后台进程运行时,我们输入的指令依然可以执行(Ctrl +c 无法终止进程,使用kill + 9 +进程pid 杀死进程)

这里的S状态其实就是上述阻塞状态;

D状态

D(disk sleep)也是休眠状态,它是深度休眠,专门针对磁盘设计的;

当进程需要将较大的数据写入到磁盘当中,在等待磁盘写入时进程的状态就是休眠状态;如果是S状态:

在内存严重不足的情况下,操作系统没办法时会通过杀死进程的方式来节省资源;如果在等待的过程中进程被操作系统杀掉,并且磁盘写入数据失败,那么就会导致数据无法再加载(数据丢失);为了避免这种情况,就可以把等待数据写入的进程状态设为D状态;

D状态无法被杀掉(OS也不行),只能等待执行完毕后状态转换;

注意:

如果用户看到了D状态,说明计算机几乎要挂掉了

T状态

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

bash 复制代码
kill -SIGSTOP  <进程ID>

使用kill指令可以查看发送给信号的所有类型:

bash 复制代码
kill -l

为什么要停止?

进程在访问资源时,可能暂时不允许进程访问,这时OS就会将进程的状态设置为stop(T状态)

t状态

t状态也是停止状态,Linux中没有进行区分;

主要出现在程序Debug时,在Debug的时候,遇到断点,进程就暂停,此时就是t状态

在上述的D状态、T状态、t状态其实都是阻塞状态,阻塞可以等待硬件资源也可以等待软件资源

比如:一个进程等待另一个进程,进程的PCB里可以有PCB* wait_queue,比如gdb的进程等待Debug的进程;

X状态

X状态(死亡状态),就是我们常说的终止状态,它是一个瞬时状态,不会在任务列表里看到这个状态

最后就是Z(zombie)僵尸状态,僵尸状态较为复杂,Linux系统中的僵尸进程状态也是一种特殊的进程状态,通常是指一个子进程已经结束运行,但其父进程还未对其进行善后处理(如调用wait()函数)。如果不及时清理僵尸进程,会导致系统资源泄漏,影响系统性能甚至造成系统崩溃;


总结

本文主要从底层出发向大家介绍了运行、阻塞、挂起这几种常见的状态,并且将Linux中具体的状态进行了一系列介绍,可以划分为这几种状态;最后是僵尸状态,僵尸状态的情况较为特殊,如果不及时处理也会造成比较严重的后果,我们下期再来进行详细的介绍,以上便是本文的全部内容,希望可以对你有所帮助,感谢阅读!

相关推荐
AlfredZhao7 小时前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户97183563346613 小时前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪14 小时前
linux 拷贝文件或目录到指定的位置
linux
大树881 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠1 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质1 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush41 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5201 天前
Linux 11 动态监控指令top
linux
Inhand陈工1 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智1 天前
ARP代理--工作原理
运维·网络·arp·arp代理