Linux:进程状态

操作系统的进程状态

在这里插入图片描述

当一个进程被执行时,内存中会载入它的PCB和代码和数据。而PCB中会有数据记录进程的状态,一般有运行状态、阻塞状态、挂起状态。

操作系统根据进程的状态,选择将进程的PCB放在不同的队列中。

所有处于运行状态的进程的PCB,都会放在运行队列中,CPU会根据程序运行状态和时间片来挨个运算每一个处于运行状态的进程。

如果一个进程需要输入或输出,而又迟迟得不到输入或输出,比如我们程序中有scanf函数,该进程希望能从键盘中得到输入,如果我们一直不输入,该程序就会处于阻塞状态,阻塞状态的PCB会被链接在对应的硬件的结构体对象中,比如上面的例子中,进程的PCB会链接在键盘结构体对象中,等待键盘输入。

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

注释的大意是,进程的状态是由一个位图存储的,运行状态是全0,其他组合代表不同的状态。

进程的状态是存储在PCB中的,因为操作系统通过管理PCB来管理进程。

查看进程状态

我们可以通过:

ps aux / ps axj 命令

来查看目前进程的运行状态。
在这里插入图片描述

运行状态

当我们创建一个进程,该进程死循环运行,我们可以查看它的状态信息。
在这里插入图片描述

当我们运行该程序后,命令行不会再被调出来,因为该进程一直未结束,这时我们登录另一个账户来查看进程信息。

在这里插入图片描述

此时我们可以看到,该程序处于运行状态R,后面的+表示该程序在前台运行,所以该程序如果不运行结束,bash命令行就不会继续执行(bash也是进程)。如果想让test后台执行,需要在调用test的时候加&
在这里插入图片描述

此时后台运行的进程我们无法用ctrl + C来结束进程,只能使用kill -9 PID
在这里插入图片描述

睡眠状态

上面的程序中,如果我们取消注释:
在这里插入图片描述

程序会循环输出
在这里插入图片描述

此时我们在另一个账户查看他的状态,就变成了S睡眠状态

在这里插入图片描述

这是符合我们预期的,因为我们程序中有sleep函数,但是如果我们注释掉sleep函数呢?

在这里插入图片描述

可以看到,程序的状态还是S,这是因为CPU的运行效率很高,而打印的效率很低,所以在这个进程大部分时间都在等待输出,而不是进行计算,所以这就符合我们一开始描述的阻塞状态,没错,睡眠状态就是一种阻塞状态。

深度睡眠状态

深度睡眠状态D也是阻塞状态的一种,也叫做磁盘休眠状态,或不可中断睡眠状态。

在这种状态下的程序无法被操作系统杀死,只能等待IO结束。

暂停状态

暂停状态T也是阻塞状态的一种,可以通过发送SIGSTOP信号给进程来停止(T)进程。这个被暂停的进程可 以通过发送SIGCONT信号让进程继续运行。

我们注释掉打印和sleep,再次运行上面的死循环,然后用kill -19 PID来让他变为暂停状态:

在这里插入图片描述

想要使其恢复运行状态,可以使用kill -18 PID
在这里插入图片描述

需要注意的是:即使是前台运行的进程,在变成暂停状态后也会变成后台进程,而且即使再恢复,也还是后台进程。

暂停状态还有另一种t,这是一种出现在调试时的状态。

如果我们使用gdb调试一个debug版的进程,而且该进程现在停在断点处,那么该进程就会处于t状态。

在这里插入图片描述

挂起状态

挂起状态也是一种阻塞状态。

当内存不足时,操作系统会将处于睡眠状态的进程的代码和数据存储在磁盘中,只留下PCB“排队”,这样就可以省出内存空间。

当进程从进程状态转为运行状态时,再将代码和数据从磁盘中写入内存中。

死亡状态

当进程运行结束,并完成资源释放后,程序就会处于死亡状态X。这个状态只是一个返回状态,用户不会在任务列表里看到这个状态。

僵尸状态

僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵尸进程。僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。

来一个创建僵尸进程例子:
在这里插入图片描述

编译,5s后查看进程状态:
在这里插入图片描述

30s后查看进程状态:

在这里插入图片描述

可以看到,子进程结束后,父进程没有释放子进程的资源,所以子进程就成了僵尸进程。而父进程结束后,自动释放自己和子进程的资源。

孤儿进程

还是上面的例子,如果父进程先退出了,子进程还在运行,那么该子进程就被称为孤儿进程。

父进程运行结束后,自己先退出了,而后子进程才运行结束,此时如果不对子进程进行资源释放,子进程就会一直维持僵尸状态,从而造成内存泄漏。

在这里插入图片描述

编译,前5s查看进程状态:
在这里插入图片描述

5s后查看进程状态:
在这里插入图片描述

可以看到,父进程推出后,子进程还在运行,而且它的PPID变成了1,PPID为1的进程就是操作系统。

也就是说,如果父进程比子进程先退出,该子进程会被操作系统“收养”,由操作系统完成子进程的资源清理。

相关推荐

  1. Linux进程状态

    2024-06-12 08:12:04       39 阅读

最近更新

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

    2024-06-12 08:12:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-12 08:12:04       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-12 08:12:04       82 阅读
  4. Python语言-面向对象

    2024-06-12 08:12:04       91 阅读

热门阅读

  1. react 0至1 【jsx】

    2024-06-12 08:12:04       33 阅读
  2. 一个有趣的c++案例

    2024-06-12 08:12:04       22 阅读
  3. “手撕”二叉树的OJ习题

    2024-06-12 08:12:04       24 阅读
  4. jQuery Ajax 基本用法 附带Fetch API

    2024-06-12 08:12:04       30 阅读
  5. cd和pwd命令

    2024-06-12 08:12:04       26 阅读
  6. Date类

    2024-06-12 08:12:04       24 阅读
  7. LINUX

    LINUX

    2024-06-12 08:12:04      29 阅读
  8. Mongodb学习

    2024-06-12 08:12:04       27 阅读
  9. 【每日一题】01

    2024-06-12 08:12:04       22 阅读