一、为什么要有进程优先级?
- 这似乎不用过多的解释,毕竟自从多任务操作系统诞生以来,进程执行占用 cpu 的能力就是一个必须要可以人为控制的事情。因为有的进程相对重要,而有的进程则没那么重要。
- 进程优先级起作用的方式从发明以来基本没有什么变化,无论是只有一个 cpu 的时代,还是多核 cpu 时代,都是通过控制进程占用 cpu 时间的长短来实现的。
就是说在同一个调度周期中,优先级高的进程占用的时间长些,而优先级低的进程占用的短些。
二、NI 和 PR
不要混淆了系统中的这两个概念:nice(NI)和 priority(PR),他们有着千丝万缕的关系,但对于当前的 Linux 系统来说,它们并不是同一个概念。
看下面这个命令:
大家是否真的明白其中 PRI 列和 NI 列的具体含义有什么区别?
同样的,如果是 top 命令:
大家是否搞清楚了这其中 PR 值和 NI 值的差别?如果没有,那么我们可以首先搞清楚什么是 nice 值。
什么是 NICE 值?
NICE 值应该是熟悉 Linux/UNIX 的人很了解的概念了,它是反应一个进程“优先级”状态的值,其取值范围是 -20至19,一共 40 个级别。
这个值越小,表示进程 “优先级” 越高,而值越大 “优先级” 越低。
例如,我们可以通过 NICE 命令来对一个将要执行的 bash 命令进行 NICE 值设置,方法是:
[root@zorrozou-pc0 zorro]# nice -n 10 bash
这样我就又打开了一个 bash,并且其 nice 值设置为 10,而默认情况下,进程的优先级应该是从父进程继承来的,这个值一般是 0。
我们可以通过 nice 命令直接查看到当前 shell 的 nice 值:
[root@zorrozou-pc0 zorro]# nice10
对比一下正常情况:
[root@zorrozou-pc0 zorro]# exit
退出当前 nice 值为 10 的 bash,打开一个正常的 bash,我们查看下其 Nice 值:
[root@zorrozou-pc0 zorro]# bash[root@zorrozou-pc0 zorro]# nice0
- 另外,使用 renice 命令可以对一个正在运行的进程进行 nice 值的调整,我们也可以使用比如 top、ps 等命令查看进程的 nice 值,具体方法大家可以参阅相关 man page。
- 需要大家注意的是,我在这里都在使用 nice 值这一称谓,而非优先级(priority)这个说法。nice 值虽然不是 priority,但是它确实可以影响进程的优先级。
- 在英语中,如果我们形容一个人 nice,那一般说明这个人的人缘比较好。什么样的人算是人缘好呢?往往是谦让、有礼貌的人。
- 比如,你跟一个 nice 的人一起去吃午饭,点了两个一样的饭,先上了一份后,nice 的那位一般都会说:“你先吃你先吃!”,这就是人缘好,这人 nice!但是如果另一份上的很晚,那么这位 nice 的人就要饿着了。
这说明什么? - 越 nice 的人抢占资源的能力就越差,而越不 nice 的人抢占能力就越强。这就是 nice 值大小的含义,nice 值越低,说明进程越不 nice,抢占 cpu 的能力就越强,优先级就越高。
在原来使用 O1 调度的 Linux 上,我们还会把 nice 值叫做静态优先级,这也基本符合 nice 值的特点,就是当 nice 值设定好了之后,除非我们用 renice 去改它,否则它是不变的。
而 priority 的值在之前内核的 O1 调度器上表现是会变化的,所以也叫做动态优先级。
什么是优先级和实时进程? - 我们再来看看什么是 priority 值,就是 ps 命令中看到的 PRI 值或者 top 命令中看到的 PR 值。本文为了区分这些概念,以后:
- 统一用 nice 值表示 NI 值,或者叫做静态优先级,也就是用 nice 和 renice 命令来调整的优先级;
- 而实用 priority 值表示 PRI 和 PR 值,或者叫动态优先级。我们也统一将 “优先级” 这个词的概念规定为表示 priority 值的意思。
在内核中,进程优先级的取值范围是通过一个宏定义的,这个宏的名称是 MAX_PRIO,它的值为 140。
而这个值又是由另外两个值相加组成的,一个是代表 nice 值取值范围的 NICE_WIDTH 宏,另一个是代表实时进程(realtime)优先级范围的 MAX_RT_PRIO 宏。
说白了就是,Linux 实际上实现了 140 个优先级范围,取值范围是从 0-139,这个值越小,优先级越高。nice 值的 -20 到 19,映射到实际的优先级范围是 100-139。
新产生进程的默认优先级被定义为:
#define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2)
实际上对应的就是 nice 值的 0。
正常情况下,任何一个进程的优先级都是这个值,即使我们通过 nice 和 renice 命令调整了进程的优先级,它的取值范围也不会超出 100-139 的范围,除非这个进程是一个实时进程,那么它的优先级取值才会变成 0-99 这个范围中的一个。