[内容] Linux 进程的理解

正文:

内容一:Linux 进程的生命周期

1) 诞生或从其它进程中分叉出来
2) 准备好运行或出于可运行的状态
3) 在用户空间或内核空间运行
4) 处于可打断的睡眠状态 (Interruptable sleep) 状态或者不可打断的睡眠状态 (Uninterruptable sleep),此时进程处于睡眠状态 (可能存储在内存中也可能存储在硬盘里的 SWAP 中)
5) 结束或处于僵尸状态

内容二:进程的分类

2.1 按进程的附属关系进行分类

分为父进程和子进程 2 种进程,其中子进程附属于父进程

子进程的特点如下:
子进程有自己单独的进程 ID
子进程的父进程 ID 就是自己父进程的 ID
子进程的资源利用率和处理器计时器会被清空
子进程的待定信号会被清空
子进程不继承父进程的内存锁
子进程不继承父进程的信号
子进程不继承父进程被锁的记录
子进程不继承父进程的计时器
子进程不继承父进程未完成的异步 I/O 操作
子进程不继承父进程任何异步 I/O 文本

2.2 按进程的使用者进行分类

分为用户进程、守护进程、系统进程

用户进程守护进程系统进程
前台运行还是后台运行通常是前台运行通常是后台运行通常是后台运行
是否开机自启通常不开机启动通常是开机自启必须是开机自启
是否可以手动管理可以手动打开或者关闭可以手动打开或者关闭不能手动打开或者关闭
是否等待或者监控服务请求 (例如 Web 服务)通常不等待新的服务请求通常在等待新的服务请求或者定期执行某些新的任务通常在等待新的服务请求
进程权限权力有限,不能超出启动此进程的用户的权力范围权力有限,不能超出启动此进程的用户的权力范围权力较大,能完全访问内核的数据结构
进程运行空间通常在用户空间里运行,可以通过 user-level processes 申请进入内核空间访问内核的数据和结构通常在用户空间里运行,可以通过 user-level processes 申请进入内核空间访问内核的数据和结构只在内核空间里运行

2.3 按进程的状态进行分类

2.3.1 按进程的状态进行分类的种类列表

分为运行状态 (Running State)、可以运行状态 (Runnable State)、可中断睡眠状态 (Interruptable Sleep State)、不可中断睡眠状态 (Uninterruptable Sleep State)、僵尸状态 (Zombie State)、关闭状态 (Defunct State)

进程名进程大类状态旗帜ps 命令中的标志是否在运行
运行状态 (Running State)Running Statep->state = TASK_RUNNINGR正在处理器上运行的进程 (a running process)
可以运行状态 (Runnable State)Runnable Statep->state = TASK_RUNNINGR不在处理器上运行的进程 (a not-running process)
可中断睡眠状态 (Interruptable Sleep State)Sleeping Statep->state = TASK_INTERRUPTABLES不在处理器上运行的进程 (a not-running process)
不可中断睡眠状态 (Uninterruptable Sleep State)Sleeping Statep->state = TASK_UNINTERRUPTABLED不在处理器上运行的进程 (a not-running process)
僵尸状态 (Zombie State)Zombie StateP->state = TASK_ZOMBIEZ不在处理器上运行的进程 (a not-running process)
关闭状态 (Defunct State)Defunct StateN/AN/A不在处理器上运行的进程 (a not-running process)

(补充:这里不可中断睡眠状态 (Uninterruptable Sleep State) 的 “D” 状态,有点像是历史遗留,因为最早这种状态被视为 “Disk Wait” 所以这种状态以 D 开头)

2.3.2 按进程的状态进行分类的种类说明
2.3.2.1 正在运行状态 (Running State)

正在处理器上运行的进程。

2.3.2.2 可以运行状态 (Runnable State)

除了处理器资源无法使用 (例如处理器资源不够或者在使用处理器资源必须要要让 I/O 进行处理的情况),其它方面都已经准备好运行的进程。

2.3.2.3 睡眠状态 (Sleeping State)

除了处理器资源,其它资源也不够被此进程使用时,进程则会进入睡眠状态。进程可能是自愿进入睡眠状态 (Sleeping State) 也可能是被内核放到睡眠状态 (Sleeping State) 里的。

当进程的资源可用时,一个信号会发送给处理器。当下次调度时,有机会安排这个处于睡眠状态 (Sleeping State) 的进程进入运行状态 (Running State) 或者是可运行状态 (Runnable State)。

有些进程永远不会结束,其会在睡眠状态 (Sleeping State) 和运行状态 (Running State) 之间来回切换。

当一个进程需要资源时,如果可用内存的容量满足这个进程,但是处理器暂时忙不过来,这个进程就会处于 Ready-to-Run state (using main memory),而当处理器又有空余资源时,这个进程就会结束 Ready-to-Run state (using main memory) 从而进入运行状态 (Running State)。而当一个进程需要资源,但内存不够满足此进程用时,则这个进程将会有进入两种状态:可中断睡眠状态 (Interruptable Sleep State) 或者不可中断睡眠状态 (Uninterruptable Sleep State)。

2.3.2.3.1 可中断睡眠状态 (Interruptable Sleep State)

进程在等待某个特殊事件的发生或者等待某个时间窗口,当某个特殊事件或者某个时间窗口发生后则会离开可中断睡眠状态 (Interruptable Sleep State)。

2.3.2.3.2 不可中断睡眠状态 (Uninterruptable Sleep State)
2.3.2.3.2.1 不可中断睡眠状态 (Uninterruptable Sleep State) 的介绍

进程在等待资源可用或者等待超时。通常发生在硬件驱动等待 disk or network I/O 时。
处于这种状态时不会处理信号,如果资源变为可用或者等待时间结束则会直接结束此状态。当处于此状态的进程回归时,会看到处于这段时间时积累的信号。

不可中断睡眠状态 (Uninterruptable Sleep State) 也是属于正常的状态,通常发生的很快因此很难被观察到。但是,如果处于不可中断睡眠状态 (Uninterruptable Sleep State) 的状态超过了合理的等待时间,那此进程会被卡住,排在此进程后面的进程也会跟着被卡住 (例如需要进入同样设备的进程或者依赖此进程的进程),这种情况下通常需要重启系统解决。

2.3.2.3.2.2 查看处于不可中断睡眠状态 (Uninterruptable Sleep State) 的进程的方法
2.3.2.3.2.2.1 方法一:单条查看
2.3.2.3.2.2.1.1 通过 ps 命令查看处于 D 状态进程的 PID 号
# ps auxH | awk '$8 ~ /^D/{print}
2.3.2.3.2.2.1.2 在系统中查看此 PID 号的堆栈信息
# sudo cat /proc/<PID>/stack
2.3.2.3.2.2.2 方法二:批量查看
# for D_PID in $(ps auxH | awk '$8 ~ /^D/{print $2}');do ps -Llp $D_PID;sudo cat /proc/$D_PID/stack;echo;done
2.3.2.4 僵尸状态 (Zombie State)

当子进程被系统叫停时,它会释放数据结构,但是它在进程表中的位置依旧会被保留。之后它会释放信号给它的父进程,由它的父进程决定此子进程是否成功退出并是否取消它在进程表中的位置。

当子进程停止,但是父进程还没有释放此进程时,此子进程将进入僵尸状态 (Zombie State)。如果父进程在释放子进程之前就死掉了,那此子进程将永远处于僵尸状态 (Zombie State)。

补充:

1) top 命令中 us 代表 user mode 用户模式,sy 代表 system mode 内核空间
2) Linux 的平均负载值为平均的 runnable or running processes (R state), and the number of processes in uninterruptable sleep (D state) over the specified interval 之和
3) 1 个处理器上同 1 时间只能运行 1 个进程

参考文献:

https://access.redhat.com/sites/default/files/attachments/processstates_20120831.pdf