【Linux】进程状态(阻塞、挂起、僵尸进程)

news/2024/11/8 22:34:51/

文章目录

  • 1 阻塞与挂起
    • 1.1 阻塞
    • 1.2 挂起
  • 2 进程状态


前言:
当我们在Windows下双击运行一个程序,或是在Linux下通过 ./ 加载运行一个程序,是否就代表对应的进程就一直处在运行状态呢?其实不然,一个进程有许多不同的状态。当我们加载运行一个程序时,并不表示其对应的进程就是一直在运行的,以Windows下运行程序来说,我们可以打开多个软件(多个应用)“同时”运行,但实际上,这些进程并不是同时处在运行状态的,CPU会不断切换调度每个需要运行的进程(分时运行),由于其切换调度的速度远超人的感知范围,因此会让人觉得所有程序在同时运行。在Linux内核里,进程有时也叫做任务,如下是kernel源代码中定义的不同的进程状态,也是本文接下来要讲述的内容。

Linux内核中进程状态定义:

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

1 阻塞与挂起

1.1 阻塞

阻塞: 进程因为等待某种条件(资源)就绪,而导致的一种不推进的状态(如我们常说的卡住了一般:页面无法响应、因网络中断下载任务无法继续执行等)。或者说,阻塞就是当前进程不被CPU调度。事实上,进程要通过等待的方式,等某个具体的资源被别人用完或者有了某个资源之后,再使用该资源。

我们知道,操作系统对软硬件做管理,其方式可以被总结为:先描述,再组织 。其中进程被描述为结构体 task_struct ,硬件被管理时同样也是被描述为一个结构体如 struct dev ,每个软硬件对应的结构体中都包括了关于自身的信息。值得注意的是,在每个硬件对应的结构体中还包含了指向进程控制块 PCB(task_struct) 的指针,可以认为该指针指向了一个进程队列的队头,通过该指针可以对某个进程队列进行管理。事实上,一个进程处在运行状态时,可以表示该进程处在CPU进程调度的运行队列中,而当某个进程因等待某种资源而无法继续推进时(通常是等待某种硬件资源,如磁盘、网卡、键盘等),CPU就会将该进程调出当前的运行队列,并调入其所等待资源对应的等待队列中(此时该进程就处在一种 阻塞 状态。换句话说,当某个进程处于阻塞状态时,就表示该进程对应的结构体 task_struct 正在某种被操作系统管理的资源下排队),当该资源准备就绪后,再将该进程调回CPU的运行队列中继续排队运行。

进程阻塞


1.2 挂起

挂起: 当因为等待某种资源就绪,进程对应PCB由运行队列转至资源下的等待队列时,考虑到内存空间紧张,CPU会将因为等待而暂时无法运行的进程对应的代码和数据先由内存转移到磁盘中,此时进程即为挂起状态,等到该进程可以被运行时再将对应的代码和数据由磁盘转移回内存中。

进程挂起


2 进程状态

进程状态


  • R(running)运行状态
    当进程处于 R 状态时,并不表示该进程一定在运行中,它表示了该进程要么是在运行中,要么是在运行队列中排队。

  • S(sleeping)睡眠状态
    意味着进程在等待某种资源就绪,该状态有时也称为 可中断睡眠状态(interruptible sleep) ,其本质就是一种阻塞状态。

  • D(disk sleep)磁盘休眠状态
    有时也称为 不可中断睡眠状态(uninterruptible sleep) ,在这个状态的进程通常会等待IO的结束。一旦一个进程处于 D 状态,则该进程不可被杀死,只有当该进程主动 “醒来(切换为其它状态)” ,其才能被终止。在绝大部分情况下都不会出现 D 状态,哪怕出现了一个 D 状态的进程,则表示当前的系统濒临崩溃。因为在正常情况下, D 状态只是一瞬间的状态,而出现该状态则表示当前磁盘空间严重不足,磁盘无法满足数据写入的需求,所以对应进程只能一直等待,进而出现 D 状态,若此时再出现几个 D 状态进程,系统就很可能崩溃死机,最后只能重启。

示例:

这里编写了一个死循环代码 test01.c ,通过 ./ 的方式运行编译生成的二进制文件 mytest 后,通过命令 ps axj | head -1 && ps axj | grep mytest | grep -v grep 查看对应的进程状态如下:


可以发现:虽然该进程看上去似乎一直在运行,但所显示的进程状态却表示其处于 S+(睡眠状态) 。这是由于在这段死循环中代码中,我们需要显示器资源来显示输出内容(这是一个进程!),显然显示器资源不会一直只供该进程使用,即该进程的运行需要等待显示器资源的就绪,也就是上述所说的睡眠状态。

下面我们又将代码中的输出语句注释,使该死循环中为空,重新编译运行,再次查看相应进程状态,此时可以看到,该进程处于 R+(运行状态) ,这是因为此时该进程不需要等待某个资源就绪,因此其一直处于运行状态。

需要注意: 与上述所说的 R / S 状态不同,这里示例中所显示的状态都多了一个 + 号,这是表示该进程在前台运行,此时,我们可以通过 Ctrl + C 的方式来终止进程;如果没有 + 号,则表示该进程在后台运行,此时可以通过 kill -9 进程PID 的方式来终止进程。

  • T(stopped)停止状态
    可以通过 kill 命令发送 SIGSTOP 信号给进程来使其进入停止状态。被暂停的进程可以再通过发送 SIGCONT 信号让进程继续运行。

示例:

  • t(tracing stop)追踪状态
    当进程正在被跟踪时,就处于 t 这个特殊状态,其本质上也是一种停止状态。例如调试程序时,触发断点而停止运行,此时对应进程就处在 t 状态。

示例:

  • X(dead)死亡状态
    该状态只是一个返回状态(瞬时状态),我们不会在任务列表里看到这个状态。事实上,我们创建进程,无非是想通过进程完成一些任务,而对于任务完成结果,我们可能关心,也可能不关心,这就涉及到一个概念 – 退出码 。所谓 退出码 ,其实就是我们编写的代码中最常见的 main()主函数中的{return 0}(也就是return的那个数字) ,我们可以通过 echo $? 命令来查看进程退出码。

示例:

  • Z(zombie)僵尸状态 / 僵尸进程
    • 僵尸状态 是一个比较特殊的状态。当进程退出并且父进程(使用wait() 系统调用)没有读取到子进程退出的返回代码时就会出现僵尸状态。

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

    • 只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程就会进入僵尸状态。

      示例:

    • 僵尸进程的危害

      • 进程的退出状态必须被维持下去,因为它要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可如果父进程一直不读取子进程状态,那子进程就会一直处于僵尸状态。
      • 维护退出状态本身需要用数据维护,也属于进程基本信息,所以保存在 task_struct(PCB) 中,换句话说,僵尸状态一直持续,其进程对应 PCB 就需要一直被维护。
      • 如果一个父进程创建了很多子进程,但就是不回收,将造成内存资源的浪费(内存泄漏),因为数据结构对象本身就要占用内存。

以上是我对Linux中进程状态相关的一些学习记录总结,如有错误,希望大家帮忙指正,也欢迎大家给予建议和讨论,谢谢!


http://www.ppmy.cn/news/31144.html

相关文章

JDK8新特性宝典

JDK8新特性 ​ Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机,Java 仍是企业和开发人员的首选开发平台 课程内容的介绍 了解Java发展史Lambda表达式…

[Tomcat]解决IDEA中的Tomcat中文乱码问题

目录 1、IDEA 2、VM options 3、IDEA启动程序的存放目录 4、Tomcat 写在前面:此方法亲测有效!!! 1、IDEA 2、VM options 加上这两行: -Dfile.encodingUTF-8 -Dconsole.encodingUTF-8 3、IDEA启动程序的存放目录…

Kubernetes ConfigMap简介

ConfigMap Service是Kubernetes系统中非常重要的一个核心概念,今天来学习另外一个非常重要的资源对象:ConfigMap,我们知道许多应用经常会有从配置文件、命令行参数或者环境变量中读取一些配置信息,这些配置信息我们肯定不会直接写…

华为OD机试 - 端口合并(C 语言解题)【独家】

最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 使用说明本期题目:端口合并…

Spring整体架构包含哪些组件?

Spring是一个轻量级java开源框架。Spring是为了解决企业应用开发的复杂性而创建的,它使用基本的JavaBean来完成以前只可能由EJB完成的事情。 Spring的用途不仅限于服务器端的开发,从简单性、可测试性和松耦合的角度而言,任何java应用都可以从…

【备战面试】TCP的三次握手与四次挥手

本篇总结的是计算机网络知识相关的面试题,后续也会更新其他相关内容 文章目录1、TCP头部结构2、三次握手3、四次挥手4、为什么TCP连接的时候是三次?两次是否可以?5、为什么TCP连接的时候是三次,关闭的时候却是四次?6、…

关于热力图展示大量数据点耗时导致浏览器崩溃问题及解决方案

目录 问题描述 问题分析 解决方案 问题描述: Web前端在地图上加载空间数据库里存储的地块中心点时因为数据点太多从而导致页面崩溃。Mybatis查询大量数据时,耗时时间更长是主要原因。8万多条数据,数据库查询最慢0.6s, Mybatis查询结果需要…

Java学习环境一站说明(保姆级详细教学)

1.Java开发环境搭建官网下载www.oracle.com2.安装注意:1.选择安装位置时尽量不要安装到C盘,路径中不要有空格以及中文的存在2.开发人员安装的jdk中包含了jre,所以不需要单独安装jre3.环境变量配置打开高级系统设置2.点击环境变量3.在系统变量…