Linux 进程调度管理
进程调度器
现代计算机系统中既包含只有单个CPU且任何时候都只能处理单个指令的低端系统到具有几百个cpu、每个cpu有多个核心的高性能超级计算机,可以并行执行几百个指令。所有这些系统都有一个共同点:系统进程线程数量超出了CPU数量。
Linux系统看起来可以同时执行多个进程,多个进程轮流使用CPU。内核使用进程调度器决定如何分配CPU时间。为了更好地运行,进程调度器必须平衡不同的条件,快速决定下个执行的进程,确保进程获得公平的CPU时间:
- 按时间片轮转(10-20ms为1个时间片 )
- 按优先级调度,允许高优先级进程获取更多的共享CPU时间,低优先级进程获取更少的共享CPU时间。


进程调度器可粗略分为两类:
- 实时调度器 ,系统中重要的进程由实时调度器调度,获得CPU能力强。
- 非实时调度器 ,系统中大部分进程由非实时调度器调度,获得CPU能力弱。
实时调度器
实时调度器支持的调度策略:
- SCHED_RR,roundrobin 轮询调度策略。相同优先级的进程轮流获取相同的CPU时间。
- SCHED_FIFO,先入先出调度策略。被分配到的CPU时间的进程会一直运行,直到被IO阻塞(也称为sched_yield),会被高优先级进程抢占。
实时调度器管理的进程运行优先级范围如下:

即使系统运行实时调度程序,也要保持可响应状态,至少ssh可用。
管理员可以使用以下两个sysctl参数,阻止实时调度策略下运行的程序占用所有CPU时间:
-
kernel.sched_rt_runtime_us,在kernel.sched_rt_period_us内实时态进程可使用的共享CPU时间,默认值950000,也就是0.95秒。设置为0,实时调度进程将无法获取CPU时间。
-
kernel.sched_rt_period_us,CPU分配的周期时间,单位us,默认值1000000,也就是1秒。
从kernel.sched_rt_period_us 中减去 kernel.sched_rt_runtime_us 后的剩余时间交给非实时调度器SCHED_NORMAL调度。
-
kernel.sched_rr_timeslice_ms,在SCHED_RR调度下的进程每次轮询获取的CPU时间,单位ms,默认值100,也就是0.1秒,有效范围1-100。
非实时调度器
非实时调度器支持的调度策略:
- SCHED_NORMAL ,标准的轮询 方式时间共享调度,也称为SCHED_OTHER。
- SCHED_BATCH ,针对批量方式执行的进程策略。不像 SCHED_NORMAL 频繁竞争,任务可以长时间运行。
- SCHED_IDLE ,用于执行非常低的优先级应用。使用 SCHED_IDLE 调度策略运行的进程比nice 19运行的进程优先级还低。
管理进程优先级
非实时调度策略
nice 值
常规系统上运行的大多数进程都使用 SCHED_OTHER 调度策略。由于并非所有进程都同等重要,因此可以为使用SCHED_OTHER调度策略运行的程序指定相对优先级,称为nice值。
有40种不同级别的nice值,范围 -20 (最高优先级)到 19(最低优先级):
- nice 值越高 ,代表优先级越低 ,获取CPU能力越弱。
- nice 值越低 ,代表优先级越高 ,获取CPU能力越强。
注意: 当不存在CPU资源竞争时,即使nice值高的进程也可以获得足够CPU资源。
nice 值查看
top 命令

ps命令
bash
[root@server ~ 14:42:13]# ps -o nice,cmd $(pgrep systemd)
NI CMD
0 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
0 /usr/lib/systemd/systemd-journald
0 /usr/lib/systemd/systemd-udevd
0 /usr/lib/systemd/systemd-logind
默认情况下,子进程将继承父进程的nice值,通常为0。
bash
[root@server ~ 14:47:54]# md5sum /dev/zero &
[1] 12321
[root@server ~ 14:48:42]# ps -o pid,nice,command $$ 12321
PID NI COMMAND
12142 0 -bash
12321 0 md5sum /dev/zero
# $$ 代表当前终端中运行的 shell 程序 PID
实时调度器进程优先级和非实时调度器进程优先级对比如下:

结论: 优先级最低的实时调度器进程的优先级高于优先级最高的非实时调度器进程的优先级。
nice 命令
bash
[root@server ~ 14:49:10]# nice --help
Usage: nice [OPTION] [COMMAND [ARG]...]
Run COMMAND with an adjusted niceness, which affects process scheduling.
With no COMMAND, print the current niceness. Niceness values range from
-20 (most favorable to the process) to 19 (least favorable to the process).
Mandatory arguments to long options are mandatory for short options too.
-n, --adjustment=N add integer N to the niceness (default 10)
--help display this help and exit
--version output version information and exit
示例:
bash
# nice值默认是10
[root@server ~ 14:49:55]# nice md5sum /dev/zero &
[2] 12331
[root@server ~ 14:50:20]# ps -o pid,nice,command
PID NI COMMAND
12142 0 -bash
12321 0 md5sum /dev/zero
12331 10 md5sum /dev/zero
12332 0 ps -o pid,nice,command
普通用户仅允许使用正数的nice值运行程序。
bash
# 设置一个负数优先级
[shizhan@server ~ 19:09:37]$ nice -n -2 md5sum /dev/zero &
[1] 7941
[shizhan@server ~ 19:10:17]$ nice: cannot set niceness: Permission denied
^C
[shizhan@server ~ 19:10:30]$ ps -o pid,nice,command 7941
PID NI COMMAND
7941 0 md5sum /dev/zero
# 设置一个正数优先级
[shizhan@server ~ 19:10:48]$ nice -n 2 md5sum /dev/zero &
[2] 8046
[shizhan@server ~ 19:11:45]$ ps -o pid,nice,command 8046
PID NI COMMAND
8046 2 md5sum /dev/zero
renice 命令
bash
[root@server ~ 14:51:06]# renice --help
Usage:
renice [-n] <priority> [-p|--pid] <pid>...
renice [-n] <priority> -g|--pgrp <pgid>...
renice [-n] <priority> -u|--user <user>...
Options:
-g, --pgrp <id> interpret argument as process group ID
-n, --priority <num> specify the nice increment value
-p, --pid <id> interpret argument as process ID (default)
-u, --user <name|id> interpret argument as username or user ID
-h, --help display help text and exit
-V, --version display version information and exit
For more information see renice(1).
修改上面示例中产生的进程的优先级。
bash
[shizhan@server ~ 19:12:04]$ renice -n 2 7941
7941 (process ID) old priority 0, new priority 2
[shizhan@server ~ 19:13:22]$ ps -o pid,nice,command 7941
PID NI COMMAND
7941 2 md5sum /dev/zero
普通用户只能升高进程nice值,不能降低。
bash
[shizhan@server ~ 19:13:44]$ renice -n -2 7941
renice: failed to set priority for 7941 (process ID): Permission denied
[shizhan@server ~ 19:14:20]$ ps -o pid,nice,command 7941
PID NI COMMAND
7941 2 md5sum /dev/zero
# 使用root用户调整
[root@server ~ 19:14:50]# renice -n -2 7941
7941 (process ID) old priority 2, new priority -2
[root@server ~ 19:15:54]# renice -n -2 8046
8046 (process ID) old priority 2, new priority -2
[root@server ~ 19:16:27]# ps -o pid,nice,command 7941 8046
PID NI COMMAND
7941 -2 md5sum /dev/zero
8046 -2 md5sum /dev/zero
top 命令
top 界面查看进程CPU使用率:7941和8046在这里插入图片描述
,CPU使用率非常接近,因为优先级一致。
在该界面中使用 r 指令设置进程nice值。
终止之前创建的3个md5sum进程。
bash
[root@server ~ 19:16:48]# pkill md5sum
实时调度策略
chrt 命令
用于获取和设置实时调度器进程优先级,以及更改进程调度器。
bash
[root@server ~ 14:53:59]# chrt --help
Show or change the real-time scheduling attributes of a process.
Set policy:
chrt [options] <priority> <command> [<arg>...]
chrt [options] --pid <priority> <pid>
Get policy:
chrt [options] -p <pid>
Policy options:
-b, --batch set policy to SCHED_BATCH
-d, --deadline set policy to SCHED_DEADLINE
-f, --fifo set policy to SCHED_FIFO
-i, --idle set policy to SCHED_IDLE
-o, --other set policy to SCHED_OTHER
-r, --rr set policy to SCHED_RR (default)
Scheduling options:
-R, --reset-on-fork set SCHED_RESET_ON_FORK for FIFO or RR
-T, --sched-runtime <ns> runtime parameter for DEADLINE
-P, --sched-period <ns> period parameter for DEADLINE
-D, --sched-deadline <ns> deadline parameter for DEADLINE
Other options:
-a, --all-tasks operate on all the tasks (threads) for a given pid
-m, --max show min and max valid priorities
-p, --pid operate on existing given pid
-v, --verbose display status information
-h, --help display this help and exit
-V, --version output version information and exit
For more details see chrt(1).
示例
bash
# 查看进程优先级范围,chrt不能用于调整非实时进程nice值优先级。
[root@server ~ 14:54:27]# chrt -m
SCHED_OTHER min/max priority : 0/0
SCHED_FIFO min/max priority : 1/99
SCHED_RR min/max priority : 1/99
SCHED_BATCH min/max priority : 0/0
SCHED_IDLE min/max priority : 0/0
SCHED_DEADLINE min/max priority : 0/0
# 以SCHED_RR调度器和优先级为5运行md5sum进程
[root@server ~ 14:54:34]# chrt -r 5 md5sum /dev/zero &
[1] 12348
[root@server ~ 14:55:03]# ps -o pid,cls,rtprio,command 12348
PID CLS RTPRIO COMMAND
12348 RR 5 md5sum /dev/zero
# top查看12348进程cpu占用95%
top - 14:56:41 up 4:37, 4 users, load average: 3.18, 1.86, 2.06
Tasks: 113 total, 2 running, 111 sleeping, 0 stopped, 0 zombie
%Cpu(s): 91.7 us, 3.3 sy, 0.0 ni, 5.0 id, 0.0 wa, 0.0 hi, 0.0 s
KiB Mem : 2027832 total, 1589680 free, 140160 used, 297992 buff
KiB Swap: 4063228 total, 4063228 free, 0 used. 1734608 avai
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+
12348 root -6 0 108068 616 524 R `95.0` 0.0 1:33.13
1 root 20 0 125520 4040 2628 S 0.0 0.2 0:01.22
# 修改进程调度器和优先级(-f先进先出)
[root@server ~ 14:55:44]# chrt -f --pid 10 12348
[root@server ~ 14:57:43]# ps -o pid,cls,rtprio,command 12348
PID CLS RTPRIO COMMAND
12348 FF 10 md5sum /dev/zero
# 此时md5sum cpu占用约95%
top - 15:00:12 up 4:41, 4 users, load average: 3.51, 2.71, 2.36
Tasks: 113 total, 2 running, 111 sleeping, 0 stopped, 0 zombie
%Cpu(s): 91.7 us, 3.3 sy, 0.0 ni, 5.0 id, 0.0 wa, 0.0 hi, 0.0 s
KiB Mem : 2027832 total, 1589648 free, 140192 used, 297992 buff
KiB Swap: 4063228 total, 4063228 free, 0 used. 1734576 avai
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+
12348 root -11 0 108068 616 524 R `94.7` 0.0 4:53.58
1 root 20 0 125520 4040 2628 S 0.0 0.2 0:01.22
# 修改进程调度器为非实时
[root@server ~ 14:57:52]# chrt -o --pid 0 12348
[root@server ~ 15:03:30]# ps -o pid,cls,rtprio,command 12348
PID CLS RTPRIO COMMAND
12348 TS - md5sum /dev/zero
top - 15:04:34 up 4:45, 4 users, load average: 2.20, 2.95, 2.58
Tasks: 114 total, 2 running, 112 sleeping, 0 stopped, 0 zombie
%Cpu(s): 96.3 us, 3.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 s
KiB Mem : 2027832 total, 1589552 free, 140272 used, 298008 buff
KiB Swap: 4063228 total, 4063228 free, 0 used. 1734488 avai
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+
12348 root 20 0 108068 616 524 R 99.9 0.0 9:05.75
661 root 20 0 273004 4792 3660 S 0.3 0.2 0:18.95
统计系统中各个进程调度,管理的进程数量
bash
[root@server ~ 15:09:30]# ps axo cls,nice,command | tee process.list |grep -v CLS | awk '{print $1}' | sort | uniq -c
3 FF
115 TS