Linux中由于需运行的进程数超过实际具有的物理核心数,所以其运用了时间片技术,操作系统进程通过调度上在每个单核心的CPU上快速的进行进程任务的切换,由于这个切换速度相当快,用户感知不到,从而使用户感觉同时有多个任务同时在运行。执行此切换的LINUX内核部分称为进程调度程序。

系统中运行的每个进程优先范围从 -20 (最高优先级)到 19 (最低优先级)。默认情况下,进程的优先级是 0 (“基本”调度优先级)。优先级比较大的进程(nice 值比较小,最低到 -20)相对优先级比较小的进程(直到 19)将比较频繁地被调度运行,因此就拥有更多的进程周期。一般用户只能降低它们自己进程的优先级别,并限于 0 到 19 之间。超级用户(root)可以将任何进程的优先级设定为任何值。便于理解,我简单画了个图,如下:

nice

一、查看nice值

上面提到的值我们习惯称之为nice (low priority user mode),我们可以通过两个最常见的命令top、ps查看nice值 。具体示例如下:

1、top查看

 1[root@361way ~]# top
 2top - 23:30:07 up 151 days, 23:56,  4 users,  load average: 0.10, 0.06, 0.01
 3Tasks:  88 total,   1 running,  87 sleeping,   0 stopped,   0 zombie
 4Cpu(s):  5.5%us,  0.5%sy,  0.0%ni, 93.9%id,  0.2%wa,  0.0%hi,  0.0%si,  0.0%st
 5Mem:   1019648k total,   944588k used,    75060k free,   221696k buffers
 6Swap:        0k total,        0k used,        0k free,   308876k cached
 7  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 8    1 root      20   0 19232  572  276 S  0.0  0.1   0:01.30 init
 9    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
10    3 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/0
11    4 root      20   0     0    0    0 S  0.0  0.0   1:16.64 ksoftirqd/0
12    5 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 stopper/0
13    6 root      RT   0     0    0    0 S  0.0  0.0   0:29.00 watchdog/0
14    7 root      20   0     0    0    0 S  0.0  0.0  11:43.55 events/0
15    8 root      20   0     0    0    0 S  0.0  0.0   0:00.00 cgroup
16    9 root      20   0     0    0    0 S  0.0  0.0   0:03.06 khelper
17   10 root      20   0     0    0    0 S  0.0  0.0   0:00.00 netns
18   11 root      20   0     0    0    0 S  0.0  0.0   0:00.00 async/mgr
19……………………省略

2、ps查看

 1[root@361way ~]# ps lax
 2F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
 34     0     1     0  20   0  19232   572 poll_s Ss   ?          0:01 /sbin/init
 41     0     2     0  20   0      0     0 kthrea S    ?          0:00 [kthreadd]
 51     0     3     2 -100  -      0     0 migrat S    ?          0:00 [migration/0]
 61     0     4     2  20   0      0     0 ksofti S    ?          1:16 [ksoftirqd/0]
 71     0     5     2 -100  -      0     0 cpu_st S    ?          0:00 [stopper/0]
 85     0     6     2 -100  -      0     0 watchd S    ?          0:29 [watchdog/0]
 91     0     7     2  20   0      0     0 worker S    ?         11:43 [events/0]
101     0     8     2  20   0      0     0 worker S    ?          0:00 [cgroup]
111     0     9     2  20   0      0     0 worker S    ?          0:03 [khelper]
121     0    10     2  20   0      0     0 worker S    ?          0:00 [netns]
131     0    11     2  20   0      0     0 async_ S    ?          0:00 [async/mgr]
141     0    12     2  20   0      0     0 worker S    ?          0:00 [pm]
155     0    13     2  20   0      0     0 xenwat S    ?          0:00 [xenwatch]
161     0    14     2  20   0      0     0 xb_wai S    ?          0:00 [xenbus]
17……………………省略

ps命令里增加l (long)参数可以查看NI项,即nice优先级值 。通过其内置的sort参数也可以对进程优先级进行排序,如下:

 1[root@361way ~]# ps axo pid,comm,nice --sort=nice
 2  PID COMMAND          NI
 3  321 udevd            -4
 4    1 init              0
 5    2 kthreadd          0
 6    3 migration/0       -
 7    4 ksoftirqd/0       0
 8    5 stopper/0         -
 9    6 watchdog/0        -
10    7 events/0          0
11    8 cgroup            0
12    9 khelper           0
13   10 netns             0
14   11 async/mgr         0
15   12 pm                0

3、PRI与NI

细心的同学估计会观察到,无论是top还是ps 里都有一个PRI 项,该值与NI值之间是什么关系呢?

我们可以理解为PRI 值是映射的NI 值, PRI 和 NI 值,都会影响进程执行的优先级 。Priority/PRI 由 OS 内核动态调整,用户不能调整(PRI 值越低,进程执行的优先级越高);Nice/NI 用户可以自己调整;相互关系:有个一般公式,PRI(new) = PRI(old) + NI ;但是,PRI 是 OS 动态调整的,但是 PRI 的最终值还需要由 OS 分析决定的(虽然 NI 会影响 PRI),详细部分可以参看下《鸟哥的LINUX私房菜》。便于理解,这里再给个图:

top-pri-ni

在RHCE-134 教材上给出了top PR值与nice的一个对应关系图,PRI 值的范围是RT\~39 ,在上面top和ps中的结果我们也看到,top中使用的最小值是RT,ps使用的-100,我们可以理解为其范围是-100~39 。上面也提到PRI是由OS自动调整的,所以两者之间的值,我们也近似的理解为PRI 20 等于NI 0 ,PRI RT 等于NI -20 优先级最高,PRI 39等于NI 19 优先级最低。

二、NI值的调整

NI 值的调整有两个相关指令,分别是nice 和 renice 。nice 命令用于在程序将要运行时,通过该指令改变其运行级别;renice是对于已经在运行的进程的优先级进行调整。

1、nice

由于进程在启动时,默认是通过继承其父进程的优先的级的,所以进程在启动时,优先级值是默认的。通过nice 修改优先级的指令如下:

1# nice  <command>
23# nice  -n 优先级值  <command>

默认不加-n 指定时,使用的nice级别为10 ,假设这里让一个test.sh 脚本的运行级别为15 ,示例如下:

1# nice -n 15  sh test.sh &

2、renice

比如在一个现网环境中,经常会遇到某些进程或资源进入死循环或被入侵式调用时,出现某个用户下的进程大量占用资源,甚至造成主机夯机的情况下,就可以通过增大该进程的nice 级别,使其相关进程排在后面执行。示例如下:

1# renice -n 7 $(pgrep nginx)

上面的例子让所有nginx 进程的优先级设为7 。

注:在实际使用中也可以通过top 按r 设置进程的ni 值。

三、总结

更多信息可以查看 nice 、renice 、top、sched_setscheduler 相关的man 手册页面。更底层的东西是通过sched进行实现的,类似的像root用户之所以更换nice值为负,是因为其具有CAP_SYS_NICE 功能权限。

就像最上面我们提到的那样,操作系统(不仅仅是linux)的多任务执行,只不过是表象上的,实际运行中是多个进程共享一个cpu资源并根据需要进行切换使用的。实际应用一般不建议修改nice值 ,该值一般让OS自动去调节即可。比如有一个CPU密集型的运算的进程在执行,如果我们将其nice值设的很低,造成的结果是该进程总是被优先进行,而由于其CPU密集运算,导致CPU长期占用在100%的状态,在该进程执行完成前,其他进程几乎没有机会执行操作。这就会导致系统可能长时间无法响应其他应用调用需求。