cpu

平均负载

查看 cpu 个数, 4 核

1
2
root@imwl01:~# grep 'model name' /proc/cpuinfo |wc -l
4

可以简单理解为 平均活跃进程数 (可运行状态 和 不可中断状态),一般认为 超过 70% 就可以排查 cpu 使用情况。4 核 即为 2.8

可运行状态: 正在使用 CPU 或者正在等待 CPU 的进程,也就是常用 ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程。

不可中断状态 : 正处于内核态关键流程中的进程,并且这些流程是不可打断的,比如最常见的是等待硬件设备的 I/O 响应,也就是 ps 命令中看到的 D 状态(Uninterruptible Sleep,也称为 Disk Sleep)的进程

1
2
root@imwl01:~# uptime
15:45:41 up 44 min, 2 user, load average: 0.12, 0.12, 0.17

15:45:41 : 当前时间
up 44 min : 开机时间
2 user : 登陆用户数

当前 1分钟 5 分钟 15分钟 很平稳

平均负载升高可能的原因:

  1. cpu 密集型导致
  2. I/O 更加繁忙

定法方法

mpstat : 查看 cpu 使用情况 mpstat -P ALL 5 1
pidstat : 查看 进程使用情况 pidstat -u 5 1

上下文切换

CPU 寄存器CPU 内置的容量小,速度极快的内存

程序寄存器 : 用来存储 CPU 正在执行的指令位置,或者即将执行的下一条指令位置

CPU 上下文切换,就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。

而这些保存下来的上下文,会存储在系统内核中,并在任务重新调度执行时再次加载进来。这样就能保证任务原来的状态不受影响,让任务看起来还是连续运行。

  1. 进程上下文切换
  2. 线程上下文切换
  3. 中断上下文切换

进程上下文切换

进程的运行空间,按 特权等级 分为: 内核空间 和 用户空间

内核空间 ( Ring 0): 可以访问所有资源

用户空间 ( Ring 3): 只能访问受限资源, 不能直接访问内存等硬件设备,需要通过系统调用陷入到内核中,才能访问这些特权资源

进程 在两个空间运行时: 进程的 用户态,内核态

进程上下文切换, 是指从一个进程切换到另一个进程

系统调用一直在同一个进程内运行。发生两次 CPU 上下文切换, 用户态 → 内核态 → 用户态。 通常称为 特权模式切换

系统调用过程通常称为特权模式切换,而不是上下文切换
进程在用户空间运行时,被称为进程的用户态,而陷入内核空间的时候,被称为进程的内核态。

从用户态到内核态的转变,需要通过系统调用来完成。

CPU 寄存器里原来用户态的指令位置,需要先保存起来。接着,为了执行内核态代码,CPU 寄存器需要更新为内核态指令的新位置。最后才是跳转到内核态运行内核任务。

而系统调用结束后,CPU 寄存器需要恢复原来保存的用户态,然后再切换到用户空间,继续运行进程。所以,一次系统调用的过程,其实是发生了两次 CPU 上下文切换

而系统调用过程中一直是同一个进程在运行。系统调用过程通常称为特权模式切换,而不是上下文切换

进程1 → 保存 进程1 上下文,加载 进程2 上下文 → 进程2

线程上下文切换

线程是调度的基本单位,而进程则是资源拥有的基本单位

当进程只有一个线程时,可以认为进程就等于线程。

当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源。这些资源在上下文切换时是不需要修改的。

另外,线程也有自己的私有数据,比如栈和寄存器等,这些在上下文切换时也是需要保存的。

因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程的私有数据、寄存器等不共享的数据

中断上下文切换

中断上下文切换并不涉及到进程的用户态。所以,即便中断过程打断了一个正处在用户态的进程,也不需要保存和恢复这个进程的虚拟内存、全局变量等用户态资源。中断上下文,其实只包括内核态中断服务程序执行所必需的状态,包括 CPU 寄存器、内核堆栈、硬件中断参数等

自愿上下文切换和非自愿上下文切换

自愿上下文切换,是指进程无法获取所需资源,导致的上下文切换。比如说, I/O、内存等系统资源不足时,就会发生自愿上下文切换。

非自愿上下文切换,则是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如说,大量进程都在争抢 CPU 时,就容易发生非自愿上下文切换

vmstat : 分析系统内存使用情况以及 cpu 上下文切换和中断的次数

DMA

Direct Memory Access(DMA)的模块,这个模块允许硬件设备直接通过 DMA 写内存,而不需要通过 CPU(占用 CPU 资源)。

相关总结

自愿上下文切换变多了,说明进程都在等待资源,有可能发生了 I/O 等其他问题;

非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢 CPU,说明 CPU 的确成了瓶颈;

中断次数变多了,说明 CPU 被中断处理程序占用,还需要通过查看 /proc/interrupts 文件来分析具体的中断类型。

备注

mpstat

1
2
3
4
5
imwl@imwl:~$ mpstat
Linux 4.4.0-22000-Microsoft (imwl) 02/10/22 _x86_64_ (16 CPU)

15:00:36 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
15:00:36 all 1.54 0.00 2.12 0.00 0.22 0.00 0.00 0.00 0.00 96.13

() 里为常用缩写

  1. user : 用户态 CPU 时间,包含 guest ( us )
  2. nice : 低优先级 (1-19) 用户态CPU 时间。(-20 ~ 19),数值越高,优先级越低 ( ni )
  3. system : 内核态 CPU 时间 (sy)
  4. idle : 空闲时间。不包括等待 I/O 的时间 ( id )
  5. iowait : 等待 I/O 的 CPU 时间 ( wa )
  6. irq : 处理硬中断的 CPU 时间 ( hi )
  7. softirq : 处理软中断的 CPU 时间 ( si )
  8. steal : 当系统运行在虚拟机中的时候,被其他虚拟机占用的 CPU 时间 ( st )
  9. guest : 代表通过虚拟化运行其他操作系统的时间,也就是运行虚拟机的 CPU 时间 ( guset )
    10.guest_nice : 以低优先级运行虚拟机的时间 ( gnice )

cpu 使用率 = 1 - 空闲时间/总cpu时间

pidstat

1
2
3
4
5
6
7
imwl@imwl:~$ pidstat
Linux 4.4.0-22000-Microsoft (imwl) 02/10/22 _x86_64_ (16 CPU)

15:00:07 UID PID %usr %system %guest %wait %CPU CPU Command
15:00:07 0 1 0.00 0.11 0.00 0.00 0.11 0 init
15:00:07 1000 9 0.00 0.09 0.00 0.00 0.09 0 bash
15:00:07 1000 378 0.01 0.00 0.00 0.00 0.01 0 pidstat

UID : 用户ID
PID : 进程识别号
PPID : 当前进程的父进程 ID

vmstat

1
2
3
4
[root@test-1 ~]# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
3 0 0 185534576 745272 22088512 0 0 3 22 1 1 4 2 93 0 0