[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 是基于时间片,进行调度轮转的,一个进程的时间片到了,就要被切换,让下一个进程被调度。