一、介绍
cpu中文名*处理器,是计算机的运算器、控制器、寄存器(2^32=4G 2^64=4亿*4G)
PAE:物理地址扩展(Physics Adress Extend),多四位,让32位操作系统寻址技术达到64G
cpu不直接操作内存,其中有多级cpu缓存,通过淘汰更新策略来与内存交换数据。每个核心有各自的L1、L2缓存,而L3缓存是共用的。如果一个进程在核心间来回切换,各个核心的缓存命中率就会受到影响。相反如果进程不管如何调度,都始终可以在一个核心上执行,那么其数据的L1、L2 缓存的命中率可以显著提高---cpu亲和性。
备注:cpu绑定及cpu间的负载均衡
二、cpu状态
1、ni:改变过优先级的进程占用CPU的百分比
2、wa:io等待占用cpu的百分比
3、hi:硬中断占用cpu的百分比
4、si:软中断占用cpu的百分比
5、steal:窃取cpu使用率,被其它虚拟机占用的cpu时间百分比
6、guest:运行客户虚拟机的 CPU 时间百分比。
三、cpu load average
单位时间内,系统处于可运行状态和不可中断状态的平均进程数,即平均活跃进程数,包括R与D状态的进程
load高的常见情况:
1、CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的;
2、I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;
3、大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。
cpu竞争造成load升高,是因为频繁进行上下文切换
还需注意程序的运行状态,僵尸进程等
四、上下文切换
cpu上下文:cpu寄存器和程序计数器(存储cpu正在执行的指令位置,或者即将执行的下一条指令位置)
上下文切换的过程:
(1)记录当前任务的上下文(即寄存器和计算器等所有的状态);
(2)找到新任务的上下文并加载;
(3)切换到新任务的程序计算器位置,恢复其任务。
linux按特权等级,将进程的运行空间分为内核空间和用户空间,Ring0-Ring3
系统调用的过程:CPU 寄存器里原来用户态的指令位置,需要先保存起来。接着,为了执行内核态代码,CPU 寄存器需要更新为内核态指令的新位置。最后才是跳转到内核态运行内核任务。而系统调用结束后,CPU 寄存器需要恢复原来保存的用户态,然后再切换到用户空间,继续运行进程。所以,一次系统调用的过程,其实是发生了两次 CPU 上下文切换。
进程是由内核来管理和调度的,进程的切换只能发生在内核态。所以,进程的上下文不仅包括了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的状态。因此,进程的上下文切换就比系统调用时多了一步:在保存当前进程的内核状态和 CPU 寄存器之前,需要先把该进程的虚拟内存、栈等保存下来;而加载了下一进程的内核态后,还需要刷新进程的虚拟内存和用户栈。
Linux 通过 TLB(Translation Lookaside Buffer)来管理虚拟内存到物理内存的映射关系。当虚拟内存更新后,TLB 也需要刷新,内存的访问也会随之变慢。特别是在多处理器系统上,缓存是被多个处理器共享的,刷新缓存不仅会影响当前处理器的进程,还会影响共享缓存的其他处理器的进程。
系统会根据程序优先级和等待时间进行排序,即进程的cpu队列
进程发生上下文切换的时间点:cpu时间片耗尽、系统资源不足时,正在执行的进程会被挂起、进程主动挂起、优先级更高的进程抢占、硬件中断
线程是调度的基本单位,进程是资源拥有的基本单位
内核中的任务调度,实际上针对的是线程,进程只是为线程提供了虚拟内存、全局变量等资源
线程的上下文切换其实就可以分为两种情况:
1、前后两个线程属于不同进程。此时,因为资源不共享,所以切换过程就跟进程上下文切换是一样。
2、前后两个线程属于同一个进程。此时,因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程的私有数据、寄存器等不共享的数据。
中断上下文切换
为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,转而调用中断处理程序,响应设备事件。而在打断其他进程时,就需要将进程当前的状态保存下来,这样在中断结束后,进程仍然可以从原来的状态恢复运行。跟进程上下文不同,中断上下文切换并不涉及到进程的用户态。所以,即便中断过程打断了一个正处在用户态的进程,也不需要保存和恢复这个进程的虚拟内存、全局变量等用户态资源。中断上下文,其实只包括内核态中断服务程序执行所必需的状态,包括 CPU 寄存器、内核堆栈、硬件中断参数等。对同一个 CPU 来说,中断处理比进程拥有更高的优先级,所以中断上下文切换并不会与进程上下文切换同时发生。同样道理,由于中断会打断正常进程的调度和执行,所以大部分中断处理程序都短小精悍,以便尽可能快的执行结束。
vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 561936 769780 5701624 0 0 20 52 0 0 4 3 93 0 0 0 0 0 561912 769780 5701624 0 0 0 0 2029 3763 0 0 100 0 0 0 1 0 559600 769780 5701624 0 0 0 36 4197 4573 5 3 92 0 0 0 0 0 560540 769780 5701652 0 0 0 4 3270 4252 2 1 98 0 0
r:Running or Runnable,就绪队列的长度,即正在运行或等待cpu的进程数
b:Blocked,处于不可中断睡眠状态的进程数
cs:Content Switch,每秒上下文切换的次数,此值过大之后用pidstat来查具体是哪些进程或线程切换次数较多,一般2万之内应该问题不大
in:Interrupt,每秒中断的次数,此值过大watch -d cat /proc/interrupts,-d表示色彩显示变化的区域
重调度中断(RES)唤醒空闲状态的 CPU 来调度新的任务运行,这是多处理器系统(SMP)中,调度器用来分散任务到不同CPU的机制,通常也被称为处理器间中断(Inter-Processor Interrupts,IPI)。
pidstat -w 1 Linux 3.10.0-957.21.3.el7.x86_64 (al-bj-op-ctrl01) 06/21/2021 _x86_64_ (4 CPU) 07:04:26 PM UID PID cswch/s nvcswch/s Command 07:04:27 PM 0 1 0.98 0.00 systemd 07:04:27 PM 0 9 61.76 0.00 rcu_sched 07:04:27 PM 0 19 0.98 0.00 ksoftirqd/2 07:04:27 PM 0 23 0.98 0.00 migration/3 07:04:27 PM 0 1382 0.98 0.00 kworker/0:1H 07:04:27 PM 0 1383 2.94 0.00 kworker/2:1H
cswch/s:voluntary context switches,自愿进行上下文切换,指进程无法获取所需资源(内存、io等系统资源不足)导致
nvcswch/s:non voluntary context switches,非自愿进行上下文切换,指进程由于时间片已到等原因,被系统强制调度
pidstat -u -w -t 1
-u:显示cpu使用率信息
-w:显示上下文切换情况
-t:显示线程的上下文切换情况
自愿上下文切换变多了,说明进程都在等待资源,有可能发生了 I/O 等其他问题
非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢 CPU,说明 CPU 的确成了瓶颈
中断次数变多了,说明 CPU 被中断处理程序占用,还需要通过查看 /proc/interrupts 文件来分析具体的中断类型。
内核空间节拍率:grep ‘CONFIG_HZ=‘ /boot/config-$(uname -r)
用户空间节拍率:getconf CLK_TCK
top指令是根据/proc/stat和节拍率等共同运算出来
perf top、perf record、perf report
有时会出现top查看没有cpu高的进程,但是系统cpu使用率却很高的情况,可能是因为占cpu的进程频繁重启造成的,top的时间间隔查看并不能显示出来,可以通过top观察处于R状态的进程,通过perf record保存到文件,再通过perf report来观察
五、中断
中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力。
linux将中断分为两部分,即上半部和下半部:
上半部:硬中断,快速处理中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关的或时间敏感的工作。
下半部:软中断,延迟处理上半部未完成的工作,通常以内核线程的方式运行。
上半部会打断cpu正在执行的任务,然后立即运行中断处理程序,下半部以内核线程的方式执行,并且每个cpu都对应一个内核软中断处理线程,名字为ksoftirqd/cpu编号(ps aux | grep ksoftirqd )
通过ps aux查看的进程信息,用中括号包住的一般为内核线程,无法获取他们的cmdline。
/proc/softirqs和/proc/interrupts可查看各类型的中断在各cpu编号上的累计运行次数,软中断基本是平均配的
NET_RX 表示网络接收中断,NET_TX 表示网络发送中断
linux软中断包括网络收发、定时、调度、RCU锁等各种类型
例子:当网卡接收到数据时,首先会发送一个硬中断请求,这个时候CPU就会执行中断处理程序,快速将网卡中数据读取到内存中,完成后会发送一个软中断请求,下半部被软中断信号唤醒后就会按照网络协议栈将内存数据进行解析处理,最终递给应用程序。(处理期间还是可以响应其他硬中断请求的)
在硬件层面,来任务后cpu必须过来处理,网卡存储数据有限,如有延迟会丢数据,所以必须把数据拿出来放到容量更大的地方,然后进入下半场--软中断,有时间再给它处理掉,软中断处理过程中是可以处理硬中断程序的
软中断问题在大流量网络中最为常见
中断过程的工作包括,应答并重新设置硬件,从设备拷贝数据到内存以及反向操作,处理硬件请求,并发送新的硬件请求。
中断处理流程:硬件-->特殊电信号(中断)-->中断处理器-->IRQ线(中断号)-->操作系统内核(调用中断处理程序,上半部)-->ksoftirqd/n(内核线程处理软中断,下半部)
因为中断打断了其他代码的执行(进程,内核本身,甚至其他中断处理程序),它们必须尽快执行完,所以内核把中断处理切分为两部分:上半部,对于时间非常敏感,硬件相关,保证不被其他中断(特别是相同中断)打断的任务,由中断处理程序处理;其他所有能够被允许稍后完成的工作推迟到下半部(任务尽可能放在下半部)。
基于Linux内核2.6,稍后执行的中断下半部使用三种方式实现:
1、软中断,可在所有处理器上同时执行,同类型也可以,仅网络和SCSI直接使用;
2、tasklet,通过软中断实现,同类型不能在处理器上同时执行,大部分下半部处理又tasklet实现;
3、工作队列,在进程上下文中执行,允许重新调度甚至睡眠,如获得大量内存、信号量、执行阻塞式I/O非常有用。
大量网络小包的分析:
网络收发软中端可首先通过 watch -d cat /proc/softirqs观察,再通过sar -n DEV 1 观察首发包数量和网络吞吐量
11:15:23 AM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s 11:15:24 AM eth0 1777.00 1666.00 668.37 859.36 0.00 0.00 0.00
rxpck/s 和 txpck/s 分别表示每秒接收、发送的网络帧数,也就是 PPS。一般2万没问题
rxkB/s 和 txkB/s 分别表示每秒接收、发送的千字节数,也就是 BPS。
如发现PPS比BPS高太多倍,则表示有很多网络小包(通过BPS*1024/PPS计算),会造成大量的网络软中断,可能是收到了syn攻击
六、优化方法论
应用程序优化:编译器、算法、异步处理、多线程代替多进程、善用缓存
系统优化:cpu绑定、cpu独占、优先级调整、为进程设置资源限制、NUMA优化、中断负载均衡(开启 irqbalance 服务或者配置 smp_affinity,就可以把中断处理过程自动负载均衡到多个 CPU 上。)