目录
操作系统的进程状态图
小编将为大家一一介绍一下进程的三种状态——运行,阻塞,挂起
运行状态

1.1个CPU对应一个运行队列,运行队列有两个进程指针,一个指向队列的头一个指向队列的尾
2.处于运行队列里的都是就绪状态,当它被CPU调度时成为运行态,当然队列里存储的都是进程的PCB,PCB又另外指向对应的进程代码和数据
3.队头 PCB 优先被调度到 CPU 运行,运行片刻后会被放回队尾,这一过程称为进程切换。
4.CPU 运行速度极快(纳秒级),我们看到的多应用 “同时运行” 是错觉,实际上 CPU 同一时刻只能执行一个进程,通过时间片轮转调度,让进程在 CPU 上快速切换执行,从而实现多进程的并发运行。PCB上都有对应的时间片信息,以及记录运行进度的结构。
阻塞状态

1.操作系统对计算机外设采用 “先描述再组织” 的管理方式。通过 DCB(设备控制块)结构体struct dev来描述设备,再利用单链表这种数据结构将这些 DCB 对象链接起来,以便于对设备进行管理。
2.当进程访问外设(如键盘)时,若外设未准备好(如键盘无用户输入处于关闭状态),进程需要等待。此时进程控制块 PCB 会被链接到 DCB 中的进程控制块 PCB 指针上,形成阻塞队列,处于该队列中的进程状态为阻塞状态。若后续还有进程需要访问该外设,会链接到阻塞进程的最后一个进程后面继续等待。
挂起状态

、
换出阶段:当操作系统内存资源不足且存在大量处于阻塞状态的进程时,会将这些阻塞状态进程对应的代码和数据从内存转移到磁盘的交换区。因为阻塞状态的进程正在等待从外设读取数据,暂时无法运行,所以即使其代码和数据不在内存中也不会影响系统运行,而磁盘空间相对内存大很多,可用于暂存这些资源。
换入阶段:当被挂起(换出)的进程等待的外设数据就绪,或者系统资源允许时,操作系统会将该进程在磁盘交换区中的代码和数据换回内存,使其进入 CPU 的运行队列,此时进程从阻塞状态转变为运行状态,能够正常执行。
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运⾏状态(running):并不意味着进程⼀定在运⾏中,它表明进程要么是在运⾏中要么在运⾏ 队列⾥。
• S睡眠状态(sleeping):意味着进程在等待事件完成(这⾥的睡眠有时候也叫做可中断睡眠 (interruptible sleep))。
• D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
• T停⽌状态(stopped):可以通过发送SIGSTOP信号给进程来停⽌(T)进程。这个被暂停的 进程可以通过发送SIGCONT信号让进程继续运⾏。
• X死亡状态(dead):这个状态只是⼀个返回状态,你不会在任务列表⾥看到这个状态。
僵尸进程
僵死状态(Zombies)是⼀个⽐较特殊的状态。当进程退出并且⽗进程(使⽤wait()系统调⽤,后 ⾯讲)没有读取到⼦进程退出的返回代码时就会产⽣僵死(⼫)进程
• 僵死进程会以终⽌状态保持在进程表中,并且会⼀直在等待⽗进程读取退出状态代码。
• 所以,只要⼦进程退出,⽗进程还在运⾏,但⽗进程没有读取⼦进程状态,⼦进程进⼊Z状态
下面我演示一下
创建一个进程,然后利用id返回值不同进行分流,让子进程退出。


可以看到子进程处于Z状态
僵尸进程的危害
1. 消耗进程表资源
Linux/Unix 系统的进程表(Process Table)容量有限(由内核参数
NR_TASKS等控制),僵尸进程会持续占用进程表中的 PCB(进程控制块)条目。当僵尸进程数量过多时,系统将无法创建新进程,表现为
fork()等系统调用失败。2. 浪费内核内存
每个僵尸进程的 PCB 会占用一定内核内存(通常为数百字节),大量僵尸进程累积会消耗宝贵的内核内存资源,间接影响系统整体性能。
3. 无法正常监控进程状态
僵尸进程的状态是 “终止但未回收”,监控工具(如
ps)会显示其状态为Z,干扰对正常进程的状态识别,增加运维排查的复杂度。4. 潜在的资源泄漏风险
若父进程长期不回收子进程,可能伴随文件描述符、网络连接等资源未释放(尽管僵尸进程本身不占用这些资源,但父进程若未正确清理,会间接引发泄漏)。
孤⼉进程
⽗进程如果提前退出,那么⼦进程后退出,进⼊Z之后,那该如何处理呢?⽗进程先退出,⼦进程就称之为“孤⼉进程” , 孤⼉进程被1号init/systemd进程领养,当然要有init/systemd进程回收喽。


把之前的代码稍微修改,可以看到当父进程退出以后,子进程未退出,但被1号进程领养,PPID变为了1,而且注意此时的子进程被操作系统收养,在后台运行,并且写的是死循环打印,那么子进程不会主动退出,那么只能使用kill -9 进程标识符,杀死子进程进行退出
进程优先级
cpu资源分配的先后顺序,就是指进程的优先权(priority)。
• 优先权⾼的进程有优先执⾏权利。配置进程优先权对多任务环境的linux很有⽤,可以改善系统性能。
• 还可以把进程运⾏到指定的CPU上,这样⼀来,把不重要的进程安排到某个CPU,可以⼤ 改善系统整体性能。

UID:代表执⾏者的⾝份
PID:代表这个进程的代号
PPID:代表这个进程是由哪个进程发展衍⽣⽽来的,亦即⽗进程的代号
PRI:代表这个进程可被执⾏的优先级,其值越⼩越早被执⾏
NI:代表这个进程的nice值
PRI and NI
PRI也还是⽐较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执⾏的先后顺序,此值越⼩进程的优先级别越⾼
• 那NI呢?就是我们所要说的nice值了,其表⽰进程可被执⾏的优先级的修正数值
• PRI值越⼩越快被执⾏,那么加⼊nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice • 这样,当nice值为负值的时候,那么该程序将会优先级值将变⼩,即其优先级会变⾼,则其越快被执⾏ 注意旧的PRI是固定的80
• 所以,调整进程优先级,在Linux下,就是调整进程nice值
• nice其取值范围是-20⾄19,⼀共40个级别。
•需要强调⼀点的是,进程的nice值不是进程的优先级,他们不是⼀个概念,但是进程nice值会影响到进程的优先级变化。
• 可以理解nice值是进程优先级的修正数据
提醒:调整进程优先级需要 root 权限,可通过两种方式获取:
su:切换为 root 用户,且不改变当前工作路径;
sudo:普通用户通过提权执行 root 权限操作。
如何更改nice值
nice调整当前bash的nice值,那么bash创建出来的子进程的nice值都会遵循bash的nice值
使用方法nice -n 你要调整的nice值 bash
用renice 不同的系统细节不太一样

竞争、独⽴、并⾏、并发
• 竞争性:系统进程数⽬众多,⽽CPU资源只有少量,甚⾄1个,所以进程之间是具有竞争属性的。为 了⾼效完成任务,更合理竞争相关资源,便具有了优先级
• 独⽴性:多进程运⾏,需要独享各种资源,多进程运⾏期间互不⼲扰
• 并⾏:多个进程在多个CPU下分别,同时进⾏运⾏,这称之为并⾏
• 并发:多个进程在⼀个CPU下采⽤进程切换的⽅式,在⼀段时间之内,让多个进程都得以推进,称 之为并发


4万+

被折叠的 条评论
为什么被折叠?



