1.实验介绍
1.1 实验内容
通过本实验我们将掌握一些 Linux 所提供的工具来进行进程的查看与控制;
掌握这些工具让我们能在某些进程出现异常的时候及时查看相关的指标,从而解决问题。
1.2 实验知识点
- 查看进程的运行状态
- 进程的结束控制
- 进程的执行顺序
2. 进程的查看
不管在测试的时候、在实际的生产环境中,还是自己的使用过程中,难免会遇到一些进程异常的情况,所以 Linux 为我们提供了一些工具来查看进程的状态信息。
我们可以通过 top 实时的查看进程的状态,以及系统的一些信息(如 CPU、内存信息等),我们还可以通过 ps 来静态查看当前的进程信息,同时我们还可以使用 pstree 来查看当前活跃进程的树形结构。
2.1 top 工具的使用
top 工具是我们常用的一个查看工具,能实时的查看我们系统的一些关键信息的变化:
top
top - 09:39:12 up 20 min, 0 users, load average: 0.00, 0.04, 0.08
Tasks: 25 total, 1 running, 24 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.8 us, 0.7 sy, 0.0 ni, 98.1 id, 0.3 wa, 0.0 hi, 0.3 si, 0.0 st
MiB Mem : 3915.9 total, 341.3 free, 1343.0 used, 2231.6 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 2303.7 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
154 root 20 0 39912 14236 8288 S 0.3 0.4 0:01.70 x11vnc
1 root 20 0 4224 3160 2716 S 0.0 0.1 0:00.03 run
95 root 20 0 34676 23908 9136 S 0.0 0.6 0:00.62 supervisord
145 root 20 0 3040 132 0 S 0.0 0.0 0:00.00 in.tftpd
149 root 20 0 12184 6976 6132 S 0.0 0.2 0:00.00 sshd
151 root 20 0 1050096 61024 43308 S 0.0 1.5 0:00.70 Xvfb
152 ubuntu 20 0 239204 27348 24504 S 0.0 0.7 0:00.08 lxsession
161 syslog 20 0 224084 3136 2140 S 0.0 0.1 0:00.19 rsyslogd
270 ubuntu 20 0 388348 8584 7288 S 0.0 0.2 0:00.01 ibus-daemon
top 是一个在前台执行的程序,所以执行后便进入到这样的一个交互界面,正是因为交互界面我们才可以实时的获取到系统与进程的信息。在交互界面中我们可以通过一些指令来操作和筛选。在此之前我们先来了解显示了哪些信息。
2.1.1 top 第一行信息
我们看到 top 显示的第一排,
内容 | 解释 |
---|---|
top | 表示当前程序的名称 |
11:05:18 | 表示当前的系统的时间 |
up 8 days,17:12 | 表示该机器已经启动了多长时间 |
1 user | 表示当前系统中只有一个用户 |
load average: 0.29,0.20,0.25 | 分别对应1、5、15分钟内cpu的平均负载 |
load average 在 wikipedia 中的解释是 the system load is a measure of the amount of work that a computer system is doing 也就是对当前 CPU 工作量的度量,
具体来说也就是指运行队列的平均长度,也就是等待 CPU 的平均进程数相关的一个计算值。
我们该如何看待这个load average 数据呢?
假设我们的系统是单 CPU、单内核的,把它比喻成是一条单向的桥,把CPU任务比作汽车。
-
load = 0 的时候意味着这个桥上并没有车,cpu 没有任何任务;
-
load < 1 的时候意味着桥上的车并不多,一切都还是很流畅的,cpu 的任务并不多,资源还很充足;
-
load = 1 的时候就意味着桥已经被车给占满了,没有一点空隙,cpu 的已经在全力工作了,所有的资源都被用完了,当然还好,这还在能力范围之内,只是有点慢而已;
-
load > 1 的时候就意味着不仅仅是桥上已经被车占满了,就连桥外都被占满了,cpu 已经在全力工作,系统资源的用完了,但是还是有大量的进程在请求,在等待。
-
若是这个值大于2、大于3,表示进程请求超过 CPU 工作能力的 2 到 3 倍。而若是这个值 > 5 说明系统已经在超负荷运作了。
这是单个 CPU 单核的情况,而实际生活中我们需要将得到的这个值除以我们的核数来看。我们可以通过以下的命令来查看 CPU 的个数与核心数
#查看物理CPU的个数
#cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l
#每个cpu的核心数
cat /proc/cpuinfo |grep "physical id"|grep "0"|wc -l
通过上面的指数我们可以得知 load 的临界值为 1 ,但是在实际生活中,比较有经验的运维或者系统管理员会将临界值定为0.7。这里的指数都是除以核心数以后的值,不要混淆了
- 若是 load < 0.7 并不会去关注他;
- 若是 0.7< load < 1 的时候我们就需要稍微关注一下了,虽然还可以应付但是这个值已经离临界不远了;
- 若是 load = 1 的时候我们就需要警惕了,因为这个时候已经没有更多的资源的了,已经在全力以赴了;
- 若是 load > 5 的时候系统已经快不行了,这个时候你需要加班解决问题了;
通常我们都会先看 15 分钟的值来看这个大体的趋势,然后再看 5 分钟的值对比来看是否有下降的趋势。
查看 busybox 的代码可以知道,数据是每 5 秒钟就检查一次活跃的进程数,然后计算出该值,然后 load 从 /proc/loadavg 中读取的。
而这个 load 的值是如何计算的呢,这是 load 的计算的源码
#define FSHIFT 11 /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point(定点) */
#define LOAD_FREQ (5*HZ) /* 5 sec intervals,每隔5秒计算一次平均负载值 */
#define CALC_LOAD(load, exp, n) \
load *= exp; \
load += n*(FIXED_1 - exp); \
load >>= FSHIFT;
unsigned long avenrun[3];
EXPORT_SYMBOL(avenrun);
/*
* calc_load - given tick count, update the avenrun load estimates.
* This is called while holding a write_lock on xtime_lock.
*/
static inline void calc_load(unsigned long ticks)
{
unsigned long active_tasks; /* fixed-point */
static int count = LOAD_FREQ;
count -= ticks;
if (count < 0) {
count += LOAD_FREQ;
active_tasks = count_active_tasks();
CALC_LOAD(avenrun[0], EXP_1, active_tasks);
CALC_LOAD(avenrun[1], EXP_5, active_tasks);
CALC_LOAD(avenrun[2], EXP_15, active_tasks);
}
}
有兴趣的朋友可以研究一下,是如何计算的。
代码中的后面这部分相当于它的计算公式
2.1.2 top 第2行信息
我们回归正题,来看 top 的第二行数据,基本上第二行是进程的一个情况统计
内容 | 解释 |
---|---|
Tasks: 26 total | 进程总数 |
1 running | 1个正在运行的进程数 |
25 sleeping | 25个睡眠的进程数 |
0 stopped | 停止的进程数 |
0 zombie | 僵尸进程数 |
2.1.3 top 第3行信息
来看 top 的第三行数据,这一行基本上是 CPU 的一个使用情况的统计了
内容 | 解释 |
---|---|
Cpu(s): 1.0%us | 用户空间 进程占用CPU百分比 |
1.0% sy | 内核空间运行占用CPU百分比 |
0.0% ni | 用户进程空间内改变过优先级的进程占用CPU百分比 |
97.9%id | 空闲CPU百分比 |
0.0%wa | 等待输入输出的CPU时间百分比 |
0.1%hi | 硬中断(Hardware IRQ)占用CPU的百分比 |
0.0%si | 软中断(Software IRQ)占用CPU的百分比 |
0.0%st | (Steal time) 是 hypervisor 等虚拟服务中,虚拟 CPU 等待实际 CPU 的时间的百分比 |
CPU 利用率是对一个时间段内 CPU 使用状况的统计,通过这个指标可以看出在某一个时间段内 CPU 被占用的情况,
而 Load Average 是 CPU 的 Load,它所包含的信息不是 CPU 的使用率状况,而是在一段时间内 CPU 正在处理以及等待 CPU 处理的进程数情况统计信息,这两个指标并不一样。
2.1.4 top 第4行信息
来看 top 的第四行数据,这一行基本上是内存的一个使用情况的统计了:
内容 | 解释 |
---|---|
8176740 total | 物理内存总量 |
8032104 used | 使用的物理内存总量 |
144636 free | 空闲内存总量 |
313088 buffers | 用作内核缓存的内存量 |
注意
系统中可用的物理内存最大值并不是 free 这个单一的值,而是 free + buffers + swap 中的 cached 的和
2.1.5 top 第5行信息
来看 top 的第五行数据,这一行基本上是交换区的一个使用情况的统计了
内容 | 解释 |
---|---|
total | 交换区总量 |
used | 使用的交换区总量 |
free | 空闲交换区总量 |
cached | 缓冲的交换区总量,内存中的内容被换出到交换区,而后又被换入到内存,但使用过的交换区尚未被覆盖 |
2.1.6 top 第6行信息
再下面就是进程的一个情况了
列名 | 解释 |
---|---|
PID | 进程id |
USER | 该进程的所属用户 |
PR | 该进程执行的优先级 priority 值 |
NI | 该进程的 nice 值 |
VIRT | 该进程任务所使用的虚拟内存的总数 |
RES | 该进程所使用的物理内存数,也称之为驻留内存数 |
SHR | 该进程共享内存的大小 |
S | 该进程进程的状态: S=sleep R=running Z=zombie |
%CPU | 该进程CPU的利用率 |
%MEM | 该进程内存的利用率 |
TIME+ | 该进程活跃的总时间 |
COMMAND | 该进程运行的名字 |
注意
2.1.7 nice值与priority 数值的关系
实时的进程因为是特殊的进程,不能等待太久,所以实时进程的优先级在0-99直接,普通进程的优先级在100-139之前。
动态优先级是内核去调整的,因为有些进程会超时,需要被惩罚。
静态优先级是用户启动一个进程的时候可以设置的优先级,这个优先级可以通过renice来改变。
NICE 值叫做静态优先级,是用户空间的一个优先级值,其取值范围是-20至19。这个值越小,表示进程”优先级”越高,而值越大“优先级”越低。nice值中的 -20 到 19, 中 -20 优先级最高, 0 是默认的值,而 19 优先级最低.
PR 值表示 Priority 值叫动态优先级,是进程在内核中实际的优先级值,进程优先级的取值范围是通过一个宏定义的,这个宏的名称是 MAX_PRIO,它的值为 140。Linux 实际上实现了 140 个优先级范围,取值范围是从 0-139,这个值越小,优先级越高。
而这其中的 0 - 99 是实时进程的值,而 100 - 139 是给用户的。
其中 PR 中的 100 to 139 值部分有这么一个对应 PR = 20 + (-20 to +19),这里的 -20 to +19 便是nice值,所以说两个虽然都是优先级,而且有千丝万缕的关系,但是他们的值,他们的作用范围并不相同.
VIRT 任务所使用的虚拟内存的总数,其中包含所有的代码,数据,共享库和被换出 swap空间的页面等所占据空间的总数。
在上文我们曾经说过 top 是一个前台程序,所以是一个可以交互的.
常用交互命令 | 解释 |
---|---|
q | 退出程序 |
I | 切换显示平均负载和启动时间的信息 |
P | 根据CPU使用百分比大小进行排序 |
M | 根据驻留内存大小进行排序 |
i | 忽略闲置和僵死的进程,这是一个开关式命令 |
k | 终止一个进程,系统提示输入 PID 及发送的信号值。一般终止进程用 15 信号,不能正常结束则使用 9 信号。安全模式下该命令被屏蔽。 |
好好的利用 top 能够很有效的帮助我们观察到系统的瓶颈所在,或者是系统的问题所在。
2.2 ps 工具的使用
ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1001 4075 3436 0 80 0 - 3489 do_wai pts/3 00:00:00 bash
4 R 1001 4081 4075 0 80 0 - 3627 - pts/3 00:00:00 ps
ps 也是我们最常用的查看进程的工具之一,我们通过这样的一个命令来了解一下,他能给我带来哪些信息
ps aux
ps axjf
respecting-god@respectinggod-Lenovo-Legion-Y7000P2020H:~/clash$ ps axjf
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 2 0 0 ? -1 S 0 0:00 [kthreadd]
2 3 0 0 ? -1 I< 0 0:00 \_ [rcu_gp]
2 4 0 0 ? -1 I< 0 0:00 \_ [rcu_par_gp]
2 6 0 0 ? -1 I< 0 0:00 \_ [kworker/0:0H-kb]
2 9 0 0 ? -1 I< 0 0:00 \_ [mm_percpu_wq]
2 10 0 0 ? -1 S 0 0:00 \_ [ksoftirqd/0]
2 11 0 0 ? -1 I 0 0:03 \_ [rcu_sched]
2 12 0 0 ? -1 S 0 0:00 \_ [migration/0]
2 13 0 0 ? -1 S 0 0:00 \_ [idle_inject/0]
2 14 0 0 ? -1 S 0 0:00 \_ [cpuhp/0]
我们来总体了解下会出现哪些信息给我们,这些信息又代表着什么(更多的 keywords 大家可以通过 man ps
了解)
内容 | 解释 |
---|---|
F | 进程的标志(process flags),当 flags 值为 1 则表示此子程序只是 fork 但没有执行 exec,为 4 表示此程序使用超级管理员 root 权限 |
USER | 进程的拥有用户 |
PID | 进程的 ID |
PPID | 其父进程的 PID |
SID | session 的 ID |
TPGID | 前台进程组的 ID |
%CPU | 进程占用的 CPU 百分比 |
%MEM | 占用内存的百分比 |
NI | 进程的 NICE 值 |
VSZ | 进程使用虚拟内存大小 |
RSS | 驻留内存中页的大小 |
TTY | 终端 ID |
S or STAT | 进程状态 |
WCHAN | 正在等待的进程资源 |
START | 启动进程的时间 |
TIME | 进程消耗CPU的时间 |
COMMAND | 命令的名称和参数 |
TPGID栏写着-1的都是没有控制终端的进程,也就是守护进程
2.3 state 状态的分类
STAT表示进程的状态,而进程的状态有很多,如下表所示
状态 | 解释 |
---|---|
R | Running.运行中 |
S | Interruptible Sleep.等待调用 |
D | Uninterruptible Sleep.不可中断睡眠 |
T | Stoped.暂停或者跟踪状态 |
X | Dead.即将被撤销 |
Z | Zombie.僵尸进程 |
W | Paging.内存交换 |
N | 优先级低的进程 |
< | 优先级高的进程 |
s | 进程的领导者 |
L | 锁定状态 |
l | 多线程状态 |
- |前台进程
其中的 D 是不能被中断睡眠的状态,处在这种状态的进程不接受外来的任何 signal,所以无法使用 kill 命令杀掉处于D状态的进程,无论是 kill,kill -9 还是 kill -15,一般处于这种状态可能是进程 I/O 的时候出问题了。
ps 工具有许多的参数,下面给大家解释部分常用的参数
使用 -l 参数可以显示自己这次登录的 bash 相关的进程信息罗列出来
ps -l
相对来说我们更加常用下面这个命令,他将会罗列出所有的进程信息
ps aux
若是查找其中的某个进程的话,我们还可以配合着 grep 和正则表达式一起使用
ps aux | grep zsh
ps axjf
此外我们还可以查看时,将连同部分的进程呈树状显示出来
通过 pstree 可以很直接的看到相同的进程数量,最主要的还是我们可以看到所有进程之间的相关性。
pstree
pstree -up
#参数选择:
#-A :各程序树之间以 ASCII 字元來連接;
#-p :同时列出每个 process 的 PID;
#-u :同时列出每个 process 的所屬账户名称。
当然如果你觉得使用这样的此时没有把你想要的信息放在一起,我们也可以是用这样的命令,来自定义我们所需要的参数显示
ps -afxo user,ppid,pid,pgid,command
这是一个简单而又实用的工具,想要更灵活的使用,想要知道更多的参数我们可以使用 man 来获取更多相关的信息
3. 进程的管理
3.1 kill -9 pid
结束进程
上个实验中我们讲述了进程之间是如何衍生,之间又有什么相关性,我们来回顾一下,当一个进程结束的时候或者要异常结束的时候,会向其父进程返回一个或者接收一个 SIGHUP 信号而做出的结束进程或者其他的操作,这个 SIGHUP 信号不仅可以由系统发送,我们可以使用 kill 来发送这个信号来操作进程的结束或者重启等等。
上节课程我们使用 kill 命令来管理我们的一些 job,这节课我们将尝试用 kill 来操作下一些不属于 job 范畴的进程,直接对 pid 下手。
#首先我们使用图形界面打开了 gedit、gvim,用 ps 可以查看到
ps aux
~/clash$ ps aux | grep vim
respect+ 13250 0.0 0.0 59316 11748 pts/3 Ss+ 09:22 0:00 vim /home/respecting-god/watch.txt
respect+ 13288 0.0 0.0 16188 1112 pts/1 S+ 09:24 0:00 grep --color=auto vim
#使用9这个信号强制结束 vim 进程
:~/clash$ kill -9 13250
#我们再查找这个进程的时候就找不到了
:~/clash$ ps aux | grep vim
respect+ 13297 0.0 0.0 16188 1012 pts/1 S+ 09:25 0:00 grep --color=auto vim
3.2 进程的优先级修改
当然就是靠该进程的优先级值来判定进程调度的优先级,而优先级的值就是上文所提到的 PR 与 nice 来控制与体现了。
nice 数值越低 表明优先级越高, 越会占用CPU 的资源, 所以nice 的意思是相对其他进程而言的, nice值越高,越不会和其他进程抢占CPU资源。
而 nice
的值我们是可以通过 renice
命令来修改的,而需要注意的是 nice
值可以调整的范围是 -20 ~ 19;nice代表进程对别的进程礼让的程度,nice越高,那么Pri值越低,但是优先级越高。
~$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1001 2960 2949 0 80 0 - 3489 do_wai pts/0 00:00:00 bash
0 T 1001 4813 2960 2 85 5 - 6918 do_sig pts/0 00:00:00 vim
4 R 1001 4814 2960 0 80 0 - 3627 - pts/0 00:00:00 ps
sudo renice -n -10 -p 2960
[sudo] shiyanlou 的密码:
2960 (process ID) 旧优先级为 0,新优先级为 -10
其中 root 有着至高无上的权力,既可以调整自己的进程也可以调整其他用户的程序,并且是所有的值都可以用;
而普通用户只可以调制属于自己的进程,并且其使用的范围只能是 0 ~ 19,因为系统为了避免一般用户抢占系统资源而设置的一个限制;
这个实验在环境中无法做,因为权限不够,可以自己在本地尝试
打开一个程序放在后台,或者用图形界面打开
nice -n -5 vim &
用 ps 查看其优先级:
ps -afxo user,ppid,pid,stat,pri,ni,time,command | grep vim
:~/clash$ ps -afxo user,ppid,pid,stat,pri,ni,time,command | grep vim
respect+ 3885 13788 S+ 19 0 00:00:00 | | \_ grep --color=auto vim
respect+ 9516 13774 T 19 0 00:00:00 | | \_ vim
respect+ 3839 13750 Ss+ 19 0 00:00:00 | \_ vim /home/respecting-god/watch.txt
优先级, 源代码地址
https://elixir.bootlin.com/linux/v2.6.32/source/include/linux/sched.h#L1561
sched.c
/*
* Convert user-nice values [ -20 ... 0 ... 19 ]
* to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
* and back.
*/
#define NICE_TO_PRIO(nice) (MAX_RT_PRIO + (nice) + 20)
#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20)
#define TASK_NICE(p) PRIO_TO_NICE((p)->static_prio)
sched.h
#define MAX_USER_RT_PRIO 100
#define MAX_RT_PRIO MAX_USER_RT_PRIO
#define MAX_PRIO (MAX_RT_PRIO + 40)
#define DEFAULT_PRIO (MAX_RT_PRIO + 20)
3.3 上下文的切换
CPU 寄存器和程序计数器就是 CPU 上下文,因为它们都是 CPU 在运行任何任务前,必须的依赖环境。
- CPU 寄存器是 CPU 内置的容量小、但速度极快的内存。
- PC 程序计数器则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。
上下文切换就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。
而这些保存下来的上下文,会存储在系统内核中,并在任务重新调度执行时再次加载进来。这样就能保证任务原来的状态不受影响,让任务看起来还是连续运行。
4. 进程的调度
我们在使用 ps 命令的时候可以看到大部分的进程都是处于休眠的状态,
如果这些进程都被唤醒,那么该谁最先享受 CPU 的服务,后面的进程又该是一个什么样的顺序呢?
进程调度的队列又该如何去排列呢?
4.1 调度算法
-
- FIFO算法:先到达的先运行,后到达的后排队。
p1 20ms
P2 10ms
P3 40ms
cpu根据先来先调度依次运行 p1 p2 p3
优势:非常简单,好实现,好理解。
缺点:前面的进程如果执行时间特别长,后面的进程根本拿不到cpu的执行,会挨饿。
-
- SJF算法:
时间最短的进程先执行。
- SJF算法:
p1 20ms
P2 10ms
P3 40ms
假设同时达到。那么执行顺序是p2, 然后p1 ,然后p3。 cpu选择那个执行时间最短的来执行,看起来是比较合适的。
但是如果p3先到达呢?那么p1,p2也还是只能等待。
优势:简单,
劣势:需要满足同时到达的条件, 但是不能解决非同时到达, 选取短时间的进程。
-
- STCF short time compelet frist:
可打断式的。如果后面的进程运行的时间小于前面的,cpu发生切换,调度时间短的进程。
优势:解决了,执行时间短的进程不需要等待时间长的进程结束。
缺点:响应时间长。进程时间长的占据时间还是太长了。
-
- RR调度算法 轮训调度算法
时间分成时间片,把时间片分给每个进程,保证大家在一个时间段都被调用到。给用户一种每个进程都在被cpu调度的假象;
4.2 调度队列
思考一个问题,计算机处理这么多的进程,
这些进程放在哪里呢?
以什么样的数据结构存储的呢?
其中,存在队列的方式存储的。
-
全局队列:
优势:实现简单
劣势:需要加锁。频繁的加锁和释放锁带来了性能的降低。 -
局部队列(每个cpu一个队列)
4.3 调度器
调度器:
每个cpu有自己的进程队列了,也有自己的优先级了。
对于cpu而言,要去找到队列当中优先级最高的队列执行,这个耗时取决于队列的长度。 遍历操作操作时间很长。
- o(1)调度器
位运算是最快的,bitmap。
140位的bitmap 每一个bit代表这个优先级上是否有进程,有的话位为1,没有的话位为0.
进程再按照先来后到的顺序排列在链表组成的队列上。
两个维护优先级的队列
一个叫active 一个叫expire
active遍历完成之后和expire交换指针。
-
- CFS调度器
O1已经是上一代调度器了,由于其对多核、多CPU系统的支持性能并不好,并且内核功能上要加入cgroup等因素,Linux在2.6.23之后开始启用CFS作为对一般优先级(SCHED_OTHER)进程调度方法。
在这个重新设计的调度器中,时间片,动态、静态优先级以及IO消耗,CPU消耗的概念都不再重要。
CFS采用了一种全新的方式,对上述功能进行了比较完善的支持。
其设计的基本思路是,我们想要实现一个对所有进程完全公平的调度器。又是那个老问题:如何做到完全公平?
答案: 跟上一篇IO调度中CFQ的思路类似:
如果当前有n个进程需要调度执行,
那么调度器应该在一个比较小的时间范围内, 把这n个进程全都调度执行一遍,并且它们平分 cpu时间,这样就可以做到所有进程的公平调度。
那么这个比较小的时间就是任意一个R状态进程被调度的最大延时时间,
即:任意一个R状态进程,都一定会在这个时间范围内被调度相应。
这个时间也可以叫做调度周期,其英文名字叫做:sched_latency_ns。
进程越多: 每个进程在周期内被执行的时间就会被平分的越小。
调度器只需要对所有进程维护一个累积占用CPU时间数,
就可以衡量出每个进程目前占用的CPU时间总量是不是过大或者过小,
这个数字记录在每个进程的vruntime中。
所有待执行进程都以vruntime为key放到一个由红黑树组成的队列中,每次被调度执行的进程,都是这个红黑树的最左子树上的那个进程,即vruntime时间最少的进程,这样就保证了所有进程的相对公平。
5. 实验小结
通过本实验我们学会了进程的查看命令 ps,pstree,top,以及使用这些命令时所得到的信息的含义,从而获取我们需要的信息,同时我们学会了进程的管理命令 kill,nice,renice
参考资料
注释1: 该例子参考于http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages;
参考资料:
https://zorrozou.github.io/docs/books/linuxde-jin-cheng-you-xian-ji.html
源码
https://elixir.bootlin.com/linux/v2.6.32/source/include/linux/sched.h#L1561
操作系统的书
http://pages.cs.wisc.edu/~remzi/OSTEP/