IBM的LPI复习资料之LPI101-Topic103 :GNU和Unix命令(6)改变进程优先级

摘要:通过设置和改变进程的优先级来让进程获得所需要的运行时间片段。

1 概述

本文讲帮你在如下几个方面打牢基础:

  • (1) 理解进程优先级
  • (2) 设置进程优先级
  • (3) 改变进程优先级

本文为备考LPIC-1的目标103.6,权重为2。

2 理解你的优先级

与其他大多数现代操作系统一样,Linux也能运行多个进程。这通过进程间共享CPU和其他资源完成。如果一个进程占用了100%的CPU,那么其他进程将会失去反应。

如果你运行top命令,默认情况下,会按照CPU占用率降序显示各个进程。前面的例子中,我们展示了一个Poor Man's Colck脚本,它每30秒打印一次当前时间,其它时间内则没有动作。top可能不会把这个进程显示出来,因为它大部分时间都没有使用CPU。

典型的top输出:

	Mem:   3924872k total,  3429320k used,   495552k free,   529468k buffers
Swap:  7574520k total,        0k used,  7574520k free,  1872160k cached
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 1580 mysql     20   0  870m  73m 6748 S  0.3  1.9 100:09.57 mysqld
14163 root      20   0 15024 1384 1008 R  0.3  0.0   0:00.06 top
    1 root      20   0 19228 1532 1248 S  0.0  0.0   0:11.62 init
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    3 root      RT   0     0    0    0 S  0.0  0.0   0:08.19 migration/0
    4 root      20   0     0    0    0 S  0.0  0.0   0:10.33 ksoftirqd/0
    5 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/0
    6 root      RT   0     0    0    0 S  0.0  0.0   0:18.44 watchdog/0
    7 root      RT   0     0    0    0 S  0.0  0.0   0:08.87 migration/1
    8 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/1
    9 root      20   0     0    0    0 S  0.0  0.0   0:14.39 ksoftirqd/1
   10 root      RT   0     0    0    0 S  0.0  0.0   0:18.44 watchdog/1
   11 root      RT   0     0    0    0 S  0.0  0.0   0:07.99 migration/2
   12 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/2
   13 root      20   0     0    0    0 S  0.0  0.0   0:14.89 ksoftirqd/2
   14 root      RT   0     0    0    0 S  0.0  0.0   0:17.60 watchdog/2
   15 root      RT   0     0    0    0 S  0.0  0.0   0:06.82 migration/3
   16 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/3
   17 root      20   0     0    0    0 S  0.0  0.0   0:05.61 ksoftirqd/3
   18 root      RT   0     0    0    0 S  0.0  0.0   0:17.79 watchdog/3
   19 root      20   0     0    0    0 S  0.0  0.0   6:35.02 events/0
   20 root      20   0     0    0    0 S  0.0  0.0   6:39.81 events/1
   21 root      20   0     0    0    0 S  0.0  0.0  70:32.21 events/2
   22 root      20   0     0    0    0 S  0.0  0.0   8:35.72 events/3
   23 root      20   0     0    0    0 S  0.0  0.0   0:00.00 cgroup
   24 root      20   0     0    0    0 S  0.0  0.0   0:00.00 khelper
   25 root      20   0     0    0    0 S  0.0  0.0   0:00.00 netns
   26 root      20   0     0    0    0 S  0.0  0.0   0:00.00 async/mgr
   27 root      20   0     0    0    0 S  0.0  0.0   0:00.00 pm
   28 root      20   0     0    0    0 S  0.0  0.0   0:45.88 sync_supers
   29 root      20   0     0    0    0 S  0.0  0.0   0:53.20 bdi-default
   30 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kintegrityd/0
   31 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kintegrityd/1
	

你的系统中可能会有一些进程使用很多的CPU资源,如视频编辑工具、图片格式转换工具或音频格式转换工具,如mp3转为ogg。

当你的机器上只有一个或者有限个数的CPU时,你需要决定如何在多个竞争进程之间共享CPU资源。这通常是通过选中一个进程让它运行一段时间(时间片),或者让它停止运行直到它等待的事件如IO完成。为了确保重要的进程不会因为CPU资源缺乏而失去反应,这种选择是基于调度优先级的。上表中的NI列代表的是进程的调度优先级,也叫做niceness。优先级通常是在-20到19之间,其中-20代表最高优先级,19代表最低优先级。

2.1 使用ps查看优先级

除了top命令外,也可以使用ps命令来显示进程优先级。使用ps -l,其输出的NI列就是进程优先级。如下所示:

[root@centos192 ~]# ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0 14148 14146  0  80   0 - 27074 wait   pts/1    00:00:00 bash
4 R     0 14548 14148  0  80   0 - 27030 -      pts/1    00:00:00 ps

2.2 默认优先级

你能已经从上面的两个例子中猜出来了,至少由普通用户启动的进程的优先级是0。这对现在的Linux系统来说是正确的。这个默认值可以通过运行不带参数的nice命令来获取。

ot@centos192 ~]# nice
0

3 设置优先级

在我们学习如何设置和改变优先级之前,先构建一个CPU密集型的脚本,它将会展示优先级确实有影响。

3.1 一个CPU密集型的脚本

我们将创建一个只使用CPU的小脚本。这个脚本使用两个输入参数,一个是计数值,一个是标签。首先会打印出这个标签和当前的系统时间,然后进入循环,每次循环都使得计数值减一,当计数值为0时终止循环,打印出标签和时间。这个测试脚本中没有进行错误检测也不是非常健壮,但是它可以说明问题了。

[root@centos192 ~]# echo 'x="$1"' > count1.sh
[root@centos192 ~]# echo 'echo "$2" $(date)' >> count1.sh
[root@centos192 ~]# echo 'while [ $x -gt 0 ]; do x=$((x-1)); done' >>count1.sh
[root@centos192 ~]# echo 'echo "$2" $(date)' >>count1.sh
[root@centos192 ~]# cat count1.sh
x="$1"
echo "$2" $(date)
while [ $x -gt 0 ]; do x=$((x-1)); done
echo "$2" $(date)

如果你在电脑上运行这个脚本,可能的输出如下:

[root@centos192 ~]# ./count1.sh 10000 A
A 2013年 08月 09日 星期五 10:30:28 CST
A 2013年 08月 09日 星期五 10:30:28 CST
[root@centos192 ~]# ./count1.sh 99000 A
A 2013年 08月 09日 星期五 10:30:43 CST
A 2013年 08月 09日 星期五 10:30:45 CST

目前位置一切安好。现在我们在后台运行这个脚本,然后使用top命令来查看其CPU占有情况。

Tasks: 188 total,   2 running, 186 sleeping,   0 stopped,   0 zombie
Cpu(s): 23.8%us,  1.2%sy,  0.0%ni, 74.8%id,  0.1%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   3924872k total,  3438424k used,   486448k free,   529588k buffers
Swap:  7574520k total,        0k used,  7574520k free,  1873432k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
29561 root      20   0  105m 1096  728 R 99.6  0.0   1:06.54 bash
  695 root      20   0     0    0    0 S  0.3  0.0   4:35.89 vmmemctl
29562 root      20   0 15024 1388 1008 R  0.3  0.0   0:00.13 top
    1 root      20   0 19228 1532 1248 S  0.0  0.0   0:11.67 init
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd

可以看出,我们的脚本使用了一个CPU的99.6的资源,如果想占用其他的CPU,则再运行上面的命令即可。如果脚本持续运行,那么将会严重影响系统的其他工作。

3.2 使用nice命令设置优先级

既然我们能够持续保持一个CPU处于繁忙状态,我们来看看如何设置一个进程的优先级。总结一下到目前为止我们学到的知识:

  • (1) Linux和Unix系统使用的优先级共有40个等级,从-20到+19.
  • (2) 普通用户启动的进程默认优先级是0.
  • (3) ps命令的-l选项可以显示进程的优先级
  • (4) nice命令来显示默认的优先级

nice除了可以显示默认优先级外,还可以用来按照指定的优先级启动一个进程。你可以使用-n(或者--adjustment)选项接一个正数来增加优先级值,接一个负数来减少优先级值。一定要记住优先级值越大,优先级越低。通常只有root用户才能指定负值,也就是说普通用户只能让进程优先级降低而不能提升。

为了演示使用nice设置优先级,我们使用相同的脚本启动两个进程,其中一个进程的优先级为19,另一个默认。一秒以后使用ps-l 来显示进程状态,包括优先级。最后我们增加了一个30秒的睡眠来保证在子sh运行完之后才退出命令。如下图所示:

[root@centos192 ~]# (sh count1.sh 2000000 A&);(nice -n 19 sh count1.sh 2000000
B&);sleep 1; ps -l; sleep 30
A 2013年 08月 09日 星期五 12:29:10 CST
B 2013年 08月 09日 星期五 12:29:10 CST
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0 29538 29536  0  80   0 - 27074 wait   pts/2    00:00:00 bash
0 R     0 30573     1 99  80   0 - 26514 -      pts/2    00:00:01 sh
0 R     0 30575     1 99  99  19 - 26514 -      pts/2    00:00:00 sh
4 R     0 30579 29538  0  80   0 - 27030 -      pts/2    00:00:00 ps
B 2013年 08月 09日 星期五 12:29:39 CST
A 2013年 08月 09日 星期五 12:29:40 CST
	

可能你会感到奇怪,这两个子进程几乎同时运行完毕。我们设置的优先级没有作用吗?请记住我们的脚本只使用一个CPU。此次运行的机器配备的是4核心的CPU。这样两2个子进程分别运行在不同的CPU核心上,也许没有必要让谁优先了。为了占满4个CPU核心,我们这次同时运行6个进程,优先级分别是0,4,8,12,16,19。

[root@centos192 ~]# (sh count1.sh 5000000 A&);(nice -n 4 sh count1.sh 5000000
B&);(nice -n 8 sh count1.sh 5000000 C&);(nice -n 12 sh count1.sh 5000000
D&);(nice -n 16 sh count1.sh 5000000 E&);(nice -n 19 sh count1.sh 5000000
F&);sleep 1; ps -l; sleep 30; 
A 2013年 08月 09日 星期五 12:25:05 CST
B 2013年 08月 09日 星期五 12:25:05 CST
C 2013年 08月 09日 星期五 12:25:05 CST
D 2013年 08月 09日 星期五 12:25:05 CST
E 2013年 08月 09日 星期五 12:25:05 CST
F 2013年 08月 09日 星期五 12:25:05 CST
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0 29538 29536  0  80   0 - 27074 wait   pts/2    00:00:00 bash
0 R     0 30471     1 50  80   0 - 26514 -      pts/2    00:00:01 sh
0 R     0 30473     1 50  84   4 - 26514 -      pts/2    00:00:01 sh
0 R     0 30475     1 49  88   8 - 26514 -      pts/2    00:00:00 sh
0 R     0 30477     1 30  92  12 - 26514 -      pts/2    00:00:00 sh
0 R     0 30480     1 12  96  16 - 26514 -      pts/2    00:00:00 sh
0 R     0 30484     1  6  99  19 - 26514 -      pts/2    00:00:00 sh
4 R     0 30489 29538  0  80   0 - 27029 -      pts/2    00:00:00 ps
C 2013年 08月 09日 星期五 12:26:19 CST
A 2013年 08月 09日 星期五 12:26:19 CST
B 2013年 08月 09日 星期五 12:26:20 CST
D 2013年 08月 09日 星期五 12:26:49 CST
E 2013年 08月 09日 星期五 12:27:15 CST
F 2013年 08月 09日 星期五 12:27:25 CST

可以看出,如此一来就会出现多个进程使用竞争CPU的情况了,基本上优先级越高,那么被执行的机会就越多,执行完毕使用的时间就越少。

最后提醒大家,如同nohup命令一样,nice命令不能使用命令列表或者管线作为参数。

4 改变优先级

4.1 renice

如果你已经启动了一个进程,之后又意识到需要改变这个进程的优先级,那么就可以使用renice命令。renice指定的是绝对优先级值而不是调整量。

i[root@centos192 ~]# sh count1.sh 10000000 A&
[1] 30799
[root@centos192 ~]# A 2013年 08月 09日 星期五 12:43:19 CST

[root@centos192 ~]# renice 1 30799; ps -l 30799
30799: old priority 0, new priority 1
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY        TIME CMD
0 R     0 30799 29538 97  81   1 - 26514 -      pts/2      0:21 sh count1.sh
10000000 A
[root@centos192 ~]# renice +3 30799; ps -l 30799
30799: old priority 1, new priority 3
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY        TIME CMD
0 R     0 30799 29538 98  83   3 - 26514 -      pts/2      0:40 sh count1.sh
10000000 A

注意,只有root用户才能提高进程的调度优先级,让进程变得不太nice。更多信息参考nice和renice的man手册页。

你可能感兴趣的:(IBM的LPI复习资料之LPI101-Topic103 :GNU和Unix命令(6)改变进程优先级)