10)上下文切换
CPU依次处理上述任务的调度方法是切换。切换分为“进程切换”“线程切换”和“中断切换”。中断切换即在本节“软中断与硬中断”中提及的,当系统中有非常重要的请求来临,CPU停止手头工作,触发硬中断。“进程切换”和“线程切换”,在切换前都要调取上次保存的信息,在切换后都要保存当前的信息。“进程切换”和“线程切换”合在一起叫做上下文切换(context switches)。图3-21为当前仅有2个任务等待CPU处理下的进程下文切换。
图3-21 进程上下文切换
由此可见上下文切换的优点在于,每个进(线)程具有同等的CPU处理权利,缺点是进(线)程的保存和载入消耗资源。由于线程信息比进程信息要少,所以线程上下文切换优于进程上下文切换。等待的进(线)程,位于CPU的最外层Ring3,而当前正在处理的进(线)程位于CPU内核,即Ring0,如图3-22所示。
图3-22 等待CPU处理的进程和正在CPU处理的进程所处CPU位置
可以通过命令vmstat interval count来查看CPU的中断数和进线程上下文切换数。在这里interval为多长描述输出一次,count为总共输出的次数。比如:“vmstat5 3”表示每5s输出一次,总共输出3次。
#vmstat 1 1
procs -----------memory---------- ---swap-- -----io-----system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 7005360 91564 818900 0 0 0 0 25 33 0 0 1000 0
这里的输出含义见表3-6所示。
表3-6 vmstat命令输出详解
总标识 | 标识 | 意义 |
---|---|---|
process | r | 展示了正在执行和等待CPU资源的任务个数。当这个值超过了CPU个数,就会出现CPU瓶颈 |
b | 每秒VMM等待队列的核心线程平均数 | |
system | in | 在某一段时间间隔中观察到的每秒设备中断数 |
cs | 在某一段时间间隔中观察到的每秒上下文切换数 | |
CPU | us | 用户方式下花费的百分比 |
sy | 系统方式下执行一个进程花费的百分比 | |
id | 没有使用本地磁盘I/O时CPU空闲或等待时间百分比 | |
wa | 等待I/O CPU时间百分比 |
在System中cs就表述在某一段时间间隔内每秒上下文切换的个数。上下文切换又分为自愿上下文切换(voluntary context switches)和非自愿上下文切换(non voluntary context switches)两种。自愿上下文切换是指到了切换时间点,进(线)程由于所需的资源不足,比如没有获得进(线)程处理所需的数据而资源CPU让出去,去处理其他进(线)程;而非自愿上下文切换是指指到了切换时间点,没有数据资源不足的情形发生,此进(线)程不得不把CPU资源让出来去处理其他正在等待的进(线)程。所以当自愿上下文切换比较多,说明I/O或者内存存在瓶颈;而非自愿上下文切换比较多,说明目前有很多进(线)程需要CPU处理。可以通过命令pidstat(需要安装sysstat插件)查看自愿上下文切换和非自愿上下文切换。
#每隔 5 秒输出 1 组数据
#pidstat -w 5
Linux 4.15.0 (ubuntu) 09/23/18 _x86_64_ (2 CPU)
08:18:26 UID PID cswch/snvcswch/s Command
08:18:31 0 1 0.20 0.00 systemd
08:18:31 0 8 5.40 0.00 rcu_sched
...
这里的cswch/s和nvcswch/s就表示每秒自愿上下文切换和非自愿上下文切换个数。
11)perf top和perf record命令
perf top命令可以显示占用 CPU 时钟最多的函数或者指令,因此可以用来查找热点函数。如图3-23所示。
图3-23 perf top
perf top 虽然实时展示了系统的性能信息,但它的缺点是并不保存数据,也就无法用于离线或者后续进行分析。
perf record 则提供了保存数据的功能,保存后的数据,需要用 perf report 解析展示。
注意:并不是所有的函数或指令都可以用perf top或perf record获得的。
12)短时进程
对于一些仅存在几毫秒的进程,当数量很大的时候也会给CPU带来很大的负载,而这些进程基本上用top或ps命令很难被获取到,这个时候就需要使用execsnoop命令了。这个命令工具可以通过https://github.com/brendangregg/perf-tools/blob/master/execsnoo获得。
13)显示10个消耗CPU最多的进程
可以通过ps aux|sort -rnk 3|head -10查看10个消耗CPU最多的进程。
#ps aux|sort -rnk 3|head -10
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 99 0.0 0.0 0 0? S 08:18 0:00 [scsi_eh_20]
root 98 0.0 0.0 0 0? S 08:18 0:00 [scsi_eh_19]
root 97 0.0 0.0 0 0? S 08:18 0:00 [scsi_eh_18]
root 96 0.0 0.0 0 0? S 08:18 0:00 [scsi_eh_17]
root 95 0.0 0.0 0 0? S 08:18 0:00 [scsi_eh_16]
root 94 0.0 0.0 0 0? S 08:18 0:00 [scsi_eh_15]
root 93 0.0 0.0 0 0? S 08:18 0:00 [scsi_eh_14]
root 92 0.0 0.0 0 0? S 08:18 0:00 [scsi_eh_13]
root 91 0.0 0.0 0 0? S 08:18 0:00 [scsi_eh_12]
14)在多CPU的系统里,查看所有CPU的信息
可以使用mpstat查看多CPU的系统里中的信息。
#mpstat
Linux 4.15.0-46-generic(ubuntu) 10/30/2019 _x86_64_(4 CPU)
02:59:04 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
02:59:04 AM all 15.29 4.91 17.24 2.76 0.00 1.08 0.00 0.00 0.00 58.71
15)小结
本节所涉及的概念有CPU负载、CPU使用率、不可中断的睡眠态进程、僵尸进程、CPU状态转换、软中断与硬中断、CPU节拍率和上下文切换。涉及到的命令有uptime、/proc/cpuinfo、top、dstat、pstree、/proc/softirqs、ps aux | grep softirq、watch、sar -n DEV 1、grep 'CONFIG_HZ=' /boot/config-$(uname -r)、vmstat、pidstat、perf top、perf record、execsnoop、ps aux|sort -rnk 3|head -10 和 mpstat。