Linux进程——进程状态

这里我们终于开始进程本身的内容了,我们之前讲操作系统管理的是进程的PCB块,那么很显然,进程状态就是PCB中的一个变量,可以使用宏定义来实现

#define NEW 1
#define RUNNING 2
#define BLOCK 3
struct PCB
{
    // ...其他配置
    int state; // 进程状态
}

这里我们主要介绍三种操作系统进程状态,分别是运行状态、阻塞状态、挂起状态,并且讲解Linux中具体的进程状态,分别是R状态(运行状态),S状态(睡眠状态)

操作系统进程状态

运行状态

现在我们使用的电脑和手机CPU说是8核心,16核心,也就是相当于CPU可以分别同时处理多个任务,我们为了方便称之为小CPU,每一个小CPU都有其对应的运行队列,他会从自己的运行队列中寻找数据来进行处理,但这里有一个容易混淆的点,就是无论这个进程是否被处理,只要他处于运行队列中,他就是运行状态

例如

image.png

以上的PCB1到PCB5,全都是运行状态

阻塞状态

我们先不去深究阻塞状态究竟是什么,先从感性上感受一下

当CPU处理一个进程时,或多或少都会访问一些外部设备,例如磁盘、网卡、键盘等

例如当你在代码中写了一个cin或者scanf的时候,系统就会等待用户输入,只要用户不输入,要访问的资源就没有就绪,此时代码就无法继续运行下去,那这个进程就处于阻塞状态,了吗??

对但不完全对,我们从操作系统的视角来看这个问题

还是之前我们所说的,想要进行管理这个操作,就要两步走,先描述、后组织

那么管理设备,也应当有一个结构体,这样操作系统才能通过访问结构体来得知设备状态,也就是这个设备是否具有访问条件,是否就绪

每一个设备的结构体中有一个独属于他的等待队列PCB* wait_queue当一个进程从运行队列移动到某设备的运行队列中,再将进程的状态改为阻塞,此时这个进程就处于阻塞状态

每个CPU或者设备都有自己的队列,而进程状态能够变化的本质就是将PCB链接到不同的队列当中,并改变PCB中表示进程状态的变量

挂起状态

我们知道,进程是需要消耗内存资源的,尤其是当进程处于阻塞状态时,他又不继续运行,又消耗内存资源

当内存资源严重不足并且有大量进程处于阻塞状态的时候,操作系统就会将这些PCB对应的数据和代码给搬到磁盘去,腾出内存让系统不至于卡死,那么这些个被搬到磁盘去的PCB,就是处于挂起状态的

在磁盘中的这部分分区是swap分区

需要注意的是,将内存数据放到外设上,是针对所有的阻塞进程的,并且这时候其实不用关心效率高低,因为如果不这样做操作系统就挂了

除此之外,swap分区在磁盘中是真实存在的,而且他的大小不会很大,主要是为了拯救一下操作系统,当内存情况缓解之后,就会被重新加载到内存

Linux的进程状态

这里是在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 */
};

我们今天主要介绍R和S状态

首先来看看我们可以在哪里看到进程状态

#include<stdio.h>
#include<unistd.h>
int main()
{
        while(1)
        {
                printf("这是一个进程");
                sleep(1);
        }
        return 0;
}

image.png

这里我们可以看到STAT一栏下面是S+,诶很奇怪,明明这是一个运行中的程序,但为什么却是S状态

这是因为屏幕循环打印,CPU处理这个循环其实很快,但是字符显示到屏幕上却很慢,因此程序大部分时间都处于阻塞状态,如果这时候一直打印查看状态,我们将看到这个程序大部分时间都处于S状态,可能百分之一的时间是R状态,而如果这个程序什么也不打印,那么他将会一直处于R状态

前后台进程

我们之前在将kill命令杀进程的时候说到过,后台进程不能通过ctrl +c来结束,只能通过kill命令来杀进程

当我们想要一个程序在后台运行的时候,只需要在运行时加上&即可

例如./a.out &

休眠状态与磁盘休眠状态

细心的同学发现这个进程状态有两个sleep

    "S (sleeping)", /* 1 */
    "D (disk sleep)", /* 2 */

我们将S状态称之为浅度睡眠,D状态称之为深度睡眠

当我们从网络上下载资源时,会遇到文件很大,下载时间很长的情况,如果这时候内存突然不够,操作系统还恰好把这个很重要的下载进程干掉了,那岂不是闯大祸了,为了防止这种在向磁盘写入重要数据时被杀掉的情况,就有了D状态

在S状态下,程序是处于浅度睡眠,是可以被主动终止的,而在D状态下,是无法被终止的程序,某些情况下甚至连断电都无法终止,除非扣主板电源()

除此之外还有一些有意思的概念,例如僵尸进程、孤儿进程,我们会在下一节的进程优先级中一并介绍

相关推荐

  1. Linux进程状态

    2024-07-14 21:52:02       32 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-14 21:52:02       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-14 21:52:02       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-14 21:52:02       45 阅读
  4. Python语言-面向对象

    2024-07-14 21:52:02       55 阅读

热门阅读

  1. helm系列之-使用helm部署应用

    2024-07-14 21:52:02       16 阅读
  2. A. Only Pluses

    2024-07-14 21:52:02       15 阅读
  3. 质量小议40 -- 合格

    2024-07-14 21:52:02       18 阅读
  4. IOS热门面试题(二)

    2024-07-14 21:52:02       17 阅读
  5. KVM-QEMU

    KVM-QEMU

    2024-07-14 21:52:02      11 阅读
  6. Linux重要知识点

    2024-07-14 21:52:02       16 阅读