一,引言
本章节会详细进程的几种状态,以及讲解为什么Linux操作系统中,同一个pcb节点可以同时适用于不同的数据结构。最后具体在Linux操作系统中去观察这几种进程状态。
二,概念解读
在操作系统课本中,进程的状态大致分为:运行,阻塞,挂起,阻塞挂起等等。如下图:

其中最核心的三种状态:运行,阻塞,挂起。下面就详细讲解一下这三种状态。
首先每一个cpu都只有一个运行队列。操作系统位于内存之中,当计算机启动时,会有大量的进程处于内存之中。但是cpu的处理能力有限,又同时有许多进程都等着被运算。因此,需要一个运行队列,来保证进程执行的先后顺序。
因此当一个进程处于运行队列时,该进程的状态处于运行状态。
当该进程从调度队列移除,进出其他队列时,该进程就进入了阻塞状态。
当内存空间过于小时,操作系统为了释放内存空间,将暂时不需要运行的进程所链接的数据和代码部分交换给磁盘的过程称为挂起状态。
三,内核链表
通常来说,一个节点只能链接一种数据结构,但是linux中的pcb节点本身处于双向带头链表中,是如何还处于队列之中的呢。这就要讲到Linux内核的链表结构。
假设Linux操作系统的进程节点属性信息是存在struct task_struct结构体之中,这个节点的内部并不是通过设置struct task_struct next*以及struct task_struct prew*指针来链接头部和尾部来实现这个链表的串联。
这struct task_struct结构体之外。linux操作系统还创建了一个结构体假设为struct list_head结构体。这个结构体内部只存放指向头部和尾部的指针。而struck 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)", /*4 */
"t (tracing stop)", /*8 *
"X (dead)", /*16 */
"Z (zombie)", /*32 */
};
r:表示运行状态。表示该进程在一直运行。如下:

s:阻塞状态,在Linux中s为可中断休眠。一般来说当进程等待输入,或者向显示屏打印等等,将进程从调度队列移向其他队列的情况都叫做,阻塞。

D:阻塞状态,在linux中D为不可中断休眠,一般来说当进程处于高度io操作时,为了防止操作系统杀掉进程,进而导致数据丢失的情况,来设置的一种进程状态。
T:暂停状态,当进程正在运行,由用户通过键盘等操作导致进程结束的情况,称之为暂停状态。
t:暂停状态,当代码处于debug模式下,位于调式的断点处暂停,这种模式成为t。
x:结束状态,当进程结束的状态
z:僵尸状态,当子进程结束,父进程需要获取到子进程的退出信息。若父进程一直没有获取到子进程的退出信息,就会导致子进程一直处于僵尸状态。这个状态会导致内存的泄漏。
当父进程先退出,子进程再退出。这种情况叫做孤儿进程。当父进程退出之后,子进程会被一个pid为1的进程所回收。
