> 技术文档 > [Linux]进程状态、优先级、切换

[Linux]进程状态、优先级、切换


一、Linux 系统中进程状态

1. R 和 S

R 代表运行状态。

S 代表的是休眠状态,但是浅睡眠,可中断的睡眠。

我们用以下代码观察一下进程的状态:

+ 表示这个进程正在前台,那为什么这个程序不是 R 运行状态,而是 S 休眠状态(本质是堵塞状态)呢?

因为相对于 IO 是很慢的,这个程序的死循环中,绝大部分时间都用来等待 IO 了,所以往往不会显示为 R 而是 S。

2. D

D 是深度休眠状态,不可中断,也是阻塞状态的一种。

这种状态产生于进程在 IO 的过程中,为了防止进程被意外杀掉导致的数据丢失风险,于是有了 disk sleep 这种状态来防止操作系统干掉这类进程。

D 状态除了及大量的 IO 数据,否则一般不会出现,如果经常见到 D 意味着磁盘可能老化或有其他问题了,是比较危险的。

3. T

暂停状态,进程被暂停。

可以用 kill -19 来暂停一个进程,用 kill -18 来继续一个进程

此时我们发现,被暂停又继续的进程,状态不带 + 号了,并且用 ^C 不能终止掉这个进程。

这是因为此时这个进程会被转入后台执行,只能通过 kill -9 来终止了。

可以用 ./ & 的方式来让程序在后台执行。

此时会先显示出进程的 PID 16412,并且即使进程再跑也可以使用命令行指令。

T 状态往往出现在一个进程做了一些非法但不致命的操作,进程被操作系统暂停。

4. t

表示进程被追踪。

当我们用gdb 调试一段代码时,代码运行到断点会停下来,本质是进程被设为了 t 状态。

5. X 和 Z

X 表示死亡状态,是终止状态。

Z 表示僵尸状态。

$? 记录着最近一个进程退出时的退出信息。

这里其实打印的就是进程 main 函数的返回值。

当一个进程无论因何种原因终止时,都是先进入 Z 状态,只释放掉进程的代码和数据占用的内存,而 task_sruct 保留,来等待采集进程的退出信息等,方便操作系统和父进程以后查询,之后才会进入 X 状态,立即被系统回收。

Z 状态的子进程会一直保持 Z 状态,也 kill 不掉,直到父进程读取过子进程 task_struct 的信息,子进程才会消失。

二、孤儿进程

当子进程的父进程先退的时候,子进程会被 init 给 1 号进程,也就是系统,交给系统来托管。

被托管给系统的子进程也就成了后台进程。

三、进程优先级

1. PRI 和 NI

用 ps -la 可以观察到进程的优先级

其中 PRI 是 priority 优先级,NI 是优先级的 nice 数据,作为优先级的修正数据

进程的最终优先级 = PRI + NI

更改一个正在进行的进程的优先级时,是先改进程的 NI,当进程下一次被调度时,PRI 会加上 NI,从而实现对进程优先级的修改。

进程有优先级,是为了争夺 CPU 资源

2. UID

每个进程也有自己的 UID,标识这个进程是谁启动的。

3.修改进程优先级

top 下按 r

OS 禁止频繁的修改,也禁止没有权限的修改(比如普通用户修改 root 用户的进程)

PRI 越高,优先程度越低。

NI 取值范围:-20 ~ 19

之所以 NI 值的调整只允许在这样一个较小的可控范围内,是因为我们民用的操作系统是分时操作系统,它追求的调度尽量公平。

为了实现调度的公平,OS不允许大幅度修改进程优先级的行为。

四、进程切换

Linux 是基于时间片,进行调度轮转的,一个进程的时间片到了,就要被切换,让下一个进程被调度。