Linux的进程调度和调整优先级
关于进程调度,应该时刻记住的是,对于我们用户来说,进程的调度完全可以看作是随机的,因为我们根本不知道下一个要调度到哪个进程。在分析多进程或多线程问题时,调度到哪个进程并不重要,重要的是进程调度的不确定性和随机性造成的影响。
在此前提下,再来了解下Linux中的进程调度器。
Linux系统中的调度器基于调度类实现,每个调度类都可以使用不同的调度算法。自Linux 2.6.23开始,标准Linux支持两种调度类:完全公平调度算法(Completely Fair Scheduler,CFS)和实时调度类(real-time scheduling class)。在Linux 2.6.23之前使用过多个调度算法,比如很长一段时间使用的是实时调度类,从2.6.23开始,已经使用CFS作为默认的调度算法。当然,Linux内核还支持其它调度算法。
无论使用什么调度算法,对使用Linux系统的用户来说,都无法直接让调度器去决定优先调度哪个进程,因为调度对用户来说是未知的。但是,用户可以通过修改优先级间接地影响Linux的调度器:优先级越高,越有可能先被调度到,优先级越低,越后被调度到。
此外,对于成熟的抢占式调度算法来说,改变进程优先级,都会影响为进程分配的时间片长度。根据之前对多级反馈队列调度算法的分析,进程的优先级越高,意味着该进程很可能是交互式或IO密集型进程,应当为其分配更短的时间片;而优先级越低,意味着该进程很可能是CPU密集型或后台服务类进程,应当为其分配更长的时间片。在Windows和Solaris系统中,确实是如此分配的,但是在Linux中正好相反,Linux为高优先级的任务分配更长的时间片,为低优先级的任务分配更短的时间片。孰优孰劣,这不是我们需要考虑的。
在Linux命令行下,可以通过nice命令或renice命令手动修改进程的nice属性值,从而改变进程的优先级。此外,还可以使用ionice命令来改变进程的IO调度优先级。它们的用法类似。
Linux的nice属性
nice和进程PID一样,是进程的一个属性,可以用来间接地影响该进程的优先级,从而改变调度程序对该进程的调度。
nice属性提供给用户的取值范围为-20~19
,默认为0。需要注意的是,值越小,优先级越高,所以-20是最高优先级,19是最低优先级。另外,只有特权用户才能使用-20~0
的优先级,普通用户只能使用正数优先级(这个限制可以使用ulimit命令修改或修改/etc/security/limit.conf文件)。如图:
从nice的范围来看,有几个比较有用的nice值:
- 19:即最低优先级,只有其它进程不想要CPU了,才会调度到该优先级的进程,是最不重要的优先级。
- 0:默认的优先级,初始时所有用户进程都处于这个级别。
- 负数:表示以高于默认优先级的重要程度来调度,这个优先级别的进程是被优待的进程。
此外,Linux支持的实时调度类(real-time scheduling class)采用两个范围的nice值,它将所有的进程分为140个优先级队列,其中nice值在0-99范围内的进程是实时进程,nice值在100-139范围内的进程是普通进程,同样的nice值越小优先级越高。其中100-139
这个范围的nice值映射到全局nice值,即-20~19
,-20对应的是100,19对应的139。如图所示。
所以,即使使用的是实时调度类,也可以使用同样的方式修改进程的优先级。而且,能修改的范围只有100-139
。
之所以0-99
不能修改,是因为这个优先级范围的进程都是实时进程。所谓实时,即响应时间非常短,交互性非常好,这类进程必须以最高优先级去调度。例如交通导航系统,响应慢了可能会导致严重灾难,像一些军用反导弹系统会使用专门定制的调度算法,因为它们要保证响应时间足够短。
nice命令和renice命令
nice和renice命令都能修改进程的优先级。它们的区别是,nice只能设置将要运行的命令的优先级,而renice可以改变已有进程的优先级。
nice命令使用-n选项指定将要运行的命令的优先级数值,范围为-20~19
(非特权用户只能使用0-19)。
例如,删除包含大量小文件的目录时,指定rm进程以低优先级运行。
$ nice -n 19 rm -rf /dir
这是一个比较有用的命令,当一个目录下包含了大量小文件,直接rm删除将会消耗大量CPU资源,这时可以指定它以最低优先级运行。当然相对应的,低优先级的rm命令可能会花费大量时间才能删除完成。如果想要快速删除,有多种技巧,比如关闭ext文件系统的日志功能、使用find+xargs+rm多进程并行删除、使用rsync删除、使用编程语言的遍历+unlink等,总之不要直接rm删除目录,因为rm直接删除目录时不够聪明,资源消耗可能会比较重(并非是因为速度慢,其实删整个目录的速度并不慢)。
renice命令可以指定已运行命令的优先级。
renice [-n] <priority> [-p|--pid] <pid>...
renice [-n] <priority> -g|--pgrp <pgid>...
renice [-n] <priority> -u|--user <user>...
-n指定优先级数值,-p选项可以指定一个或多个pid的优先级,使用-g选项可以指定进程组内所有进程的优先级,使用-u选项可以指定该用户的所有进程优先级。
例如,修改sleep进程的优先级
$ sleep 30&
[1] 64121
$ renice +10 64121
64121 (process ID) old priority 0, new priority 10
$ renice +10 64121
64121 (process ID) old priority 10, new priority 10
再例如,修改PID为987和32的进程以及daemon和root用户的进程的优先级为1。
$ renice +1 987 -u daemon root -p 32
ionice命令
ionice命令可以修改已有进程的IO调度优先级,也可以让某命令以指定的IO调度优先级运行。IO调度优先级越高,意味着获取磁盘的时间越长。
ionice [OPTION] -p PID [PID...]
ionice [OPTION] COMMAND
选项说明:
-c, --class <class>:指定调度类,支持0: none, 1: realtime, 2: best-effort, 3: idle
-n, --classdata <num>:指定调度类的优先级数值,支持0-7共8个优先级值
-p, --pid=PID:指定要查看或修改的进程的pid值
一般renice只会使用idle(3)和best-effort(2)这两种调度类,none调度类从Linux 2.6.26开始默认使用CFQ I/O调度算法后不再使用,在此之前它代表的是那些没有发出IO请求的进程。而realtime的IO调度类表现不佳,所以现在也不用,renice时也不建议使用。
idle调度类没有参数,它直接表示最低IO调度的优先级。
best-effort是默认的IO调度类,其参数值为0-7,0优先级最高,7优先级最低。
例如,修改sleep进程,使其优先级最低。
$ sleep 30 &
[1] 64244
$ ionice -c 3 -p 64244
$ ionice -n 7 -p 64244
再例如,rm删除大文件时,指定其以低IO优先级运行。
$ ionice -n 7 rm -rf huge-file.log
和删除包含大量文件的目录一样,这个命令也是比较有用的。当删除一个大文件,将会占用大量磁盘IO(和具体的文件系统有关),耗时也会较长(也和具体的文件系统有关),有时候会想让它以低优先级的方式运行,以便将磁盘资源交给其它重要的进程,那么就可以这样做。删除大文件更好的方法,是使用truncate或重定向截断大文件,或者使用/dev/null来清空文件。
此外,ionice和nice可以结合起来使用。例如:
$ nice -n 19 ionice -n 3 COMMAND
$ ionice -n 3 nice -n 19 COMMAND
提示:高效删除大量小文件
如果一个目录中包含了大量小文件。
如果是删除目录中部分文件:
(1).find /tmp/temp/ -type f -name "*.jpg" -print0 | xargs -0 -P4 -n20000 rm -rf
(2).cd /tmp/temp/; perl -e 'unlink for (<"*.jpg">)'如果是删除目录中所有文件:
(1).rm -rf /tmp/temp;mkdir -p /tmp/temp
(2).mkdir /tmp/empty;rsync -r --delete /tmp/empty/ /tmp/temp/
(3).cd /tmp/temp/; perl -e 'unlink for (<"*">)'
来源:oschina
链接:https://my.oschina.net/u/4332520/blog/3233374