一、引言
本章节详细介绍进程的几种状态,讲解为什么 Linux 操作系统中同一个 PCB 节点可以同时适用于不同的数据结构,并在 Linux 操作系统中观察这几种进程状态。
二、概念解读
在操作系统课本中,进程的状态大致分为:运行、阻塞、挂起、阻塞挂起等。

其中最核心的三种状态:运行、阻塞、挂起。下面详细讲解这三种状态。
每个 CPU 都只有一个运行队列。操作系统位于内存之中,当计算机启动时,会有大量进程处于内存之中。但 CPU 处理能力有限,同时有许多进程等待运算。因此需要一个运行队列来保证进程执行的先后顺序。
当一个进程处于运行队列时,该进程的状态处于运行状态。
当该进程从调度队列移除,进入其他队列时,该进程就进入了阻塞状态。
当内存空间过于紧张时,操作系统为了释放内存空间,将暂时不需要运行的进程所链接的数据和代码部分交换给磁盘的过程称为挂起状态。
三、内核链表
通常来说,一个节点只能链接一种数据结构,但是 Linux 中的 PCB 节点本身处于双向带头链表中,是如何还处于队列之中的呢?这就要讲到 Linux 内核的链表结构。
假设 Linux 操作系统的进程节点属性信息是存在 struct task_struct 结构体之中,这个节点的内部并不是通过设置 struct task_struct next* 以及 struct task_struct prev* 指针来链接头部和尾部来实现这个链表的串联。
在 struct task_struct 结构体之外,Linux 操作系统还创建了一个结构体假设为 struct list_head 结构体。这个结构体内部只存放指向头部和尾部的指针。而 struct task_struct 结构体内部存放了 struct list_head 结构体。

通过如下图的模式进行链接,实现了双向链表的形式。但是一个 struct task_struct 内部不仅仅只能存在一个 list_head 结构体。可以给内部存入多个类似的结构体来实现不同的链接,进而实现数据结构。

四、Linux 的进程状态
在上文中讲到操作系统的进程状态有以上几种。但是具体到 Linux 的操作系统又有些区别。具体的 Linux 操作系统的状态分为以下几种:
static const char *const task_state_array[] = {
"R (running)", /*0 */
"S (sleeping)", /*1 */
"D (disk sleep)", /*2 */
"T (stopped)",
,
,
,
};




