Linux教程

记最近Linux中遇到cpu使用率低loadavg高的分析过程

本文主要是介绍记最近Linux中遇到cpu使用率低loadavg高的分析过程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

首先明确一下CPU使用率和loadavg这两个概念:

CPU使用率

指当前CPU正在执行指令的繁忙程度,越高表面CPU正在执行很多指令即有进程一直在cpu上运行着

Loadavg

指的是CPU负载程度,表明的是CPU当前正在运行的任务以及等待运行的任务统计,是一种趋势的体现;更详细一点来说是R和D状态的进程数量统计

分析此问题的起因是前一段时间购买的开发板,使用最新的SDK跑起来后,几乎没有什么任务在运行,CPU 100% idle,但是loadavg一直在1以上(cpu是双核A7),对比之前使用过的单核MIPS架构路由器来说,显得非常不正常。

在分析开始之前,先要介绍几个工具:

top:查看进程状态以及CPU占用和loadavg参数

ps -aux: 查看进程cpu占用和运行状态

vmstat:查看cpu户空间和内核空间占用情况及系统中断和上下文切换状态

pidstat:查看具体某个进程对cpu占用和上下文切换状态

iostat:查看系统IO负载状态

首先看一下系统状态:

root@wireless-tag:/# vmstat  -w 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        75660         3948        11740    0    0     0     0   57  108   2   6  91   0   0
 0  0            0        75664         3948        11740    0    0     0     0   58   51   0   0 100   0   0
 0  0            0        75664         3948        11740    0    0     0     0   43   49   0   0 100   0   0
 0  0            0        75664         3948        11740    0    0     0     0   45   56   0   0 100   0   0
 0  0            0        75664         3948        11740    0    0     0     0   46   53   0   0 100   0   0
 0  0            0        75664         3948        11740    0    0     0     0   46   57   0   0 100   0   0
 0  0            0        75664         3948        11740    0    0     0     0   43   52   0   0 100   0   0
 0  0            0        75664         3948        11740    0    0     0     0   42   49   0   0 100   0   0

 cpu 100% idle: 说明几乎没有进程在使用cpu,中断以及上下文切换也很低

 r及b队列数量为0

root@wireless-tag:/# iostat
Linux 4.9.84 (wireless-tag)     01/01/70        _armv7l_        (2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
                 0.57      0.00      1.73        0.02         0.00   97.68

Device             tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
mtdblock0         0.03         0.41         0.00        168          0
mtdblock1         0.03         0.41         0.00        168          0
mtdblock2         0.03         0.41         0.00        168          0
mtdblock3         0.03         0.41         0.00        168          0
mtdblock4         0.03         0.41         0.00        168          0
mtdblock5         0.03         0.41         0.00        168          0
mtdblock6         0.03         0.41         0.00        168          0
mtdblock7         0.03         0.41         0.00        168          0
mtdblock8         0.03         0.41         0.00        168          0
mtdblock9         0.03         0.41         0.00        168          0
mtdblock10        0.02         0.38         0.00        156          0
mtdblock11        0.02         0.38         0.00        156          0
mtdblock12        0.02         0.38         0.00        156          0
ubiblock0_1       0.15         9.66         0.00       3948          0
zram0             0.00         0.01         0.01          4          4

 io也几乎都是空闲%idle 97.68

root@wireless-tag:/# uptime
 23:03:15 up 4 min,  0 users,  load average: 1.10, 0.67, 0.29

但是loadavg 1分钟统计显示1.10,结合前面r和b队列为0,说明系统有进程一直在等待运行

接着看一下进程列表:

 root@wireless-tag:/# ps -aux
USER      PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root        1  0.3  1.6   2596  1736 ?        Ss   22:58   0:02 /sbin/procd
root        2  0.0  0.0      0     0 ?        S    22:58   0:00 [kthreadd]
root        3  0.0  0.0      0     0 ?        S    22:58   0:00 [ksoftirqd/0]
root        5  0.0  0.0      0     0 ?        S<   22:58   0:00 [kworker/0:0H]
root        7  0.0  0.0      0     0 ?        S    22:58   0:00 [rcu_preempt]
root        8  0.0  0.0      0     0 ?        S    22:58   0:00 [rcu_sched]
root        9  0.0  0.0      0     0 ?        S    22:58   0:00 [rcu_bh]
root       10  0.0  0.0      0     0 ?        S    22:58   0:00 [migration/0]
root       11  0.0  0.0      0     0 ?        S<   22:58   0:00 [lru-add-drain]
root       12  0.0  0.0      0     0 ?        S    22:58   0:00 [watchdog/0]
root       13  0.0  0.0      0     0 ?        S    22:58   0:00 [cpuhp/0]
root       14  0.0  0.0      0     0 ?        S    22:58   0:00 [cpuhp/1]
root       15  0.0  0.0      0     0 ?        S    22:58   0:00 [watchdog/1]
root       16  0.0  0.0      0     0 ?        S    22:58   0:00 [migration/1]
root       17  0.0  0.0      0     0 ?        S    22:58   0:00 [ksoftirqd/1]
root       18  0.0  0.0      0     0 ?        S    22:58   0:00 [kworker/1:0]
root       19  0.0  0.0      0     0 ?        S<   22:58   0:00 [kworker/1:0H]
root       20  0.1  0.0      0     0 ?        S    22:58   0:00 [kdevtmpfs]
root       21  0.0  0.0      0     0 ?        S<   22:58   0:00 [netns]
root       22  0.0  0.0      0     0 ?        S    22:58   0:00 [kworker/u4:1]
root      173  0.0  0.0      0     0 ?        S    22:58   0:00 [oom_reaper]
root      174  0.0  0.0      0     0 ?        S<   22:58   0:00 [writeback]
root      176  0.0  0.0      0     0 ?        S    22:58   0:00 [kcompactd0]
root      177  0.0  0.0      0     0 ?        S<   22:58   0:00 [crypto]
root      178  0.0  0.0      0     0 ?        S<   22:58   0:00 [bioset]
root      180  0.0  0.0      0     0 ?        S<   22:58   0:00 [kblockd]
root      201  0.0  0.0      0     0 ?        S<   22:58   0:00 [watchdogd]
root      282  0.0  0.0      0     0 ?        S    22:58   0:00 [kworker/0:1]
root      296  0.0  0.0      0     0 ?        S    22:58   0:00 [kswapd0]
root      297  0.0  0.0      0     0 ?        S<   22:58   0:00 [vmstat]
root      384  0.0  0.0      0     0 ?        D    22:58   0:00 [ehci_monitor]   ----->注意状态为D
root      400  0.0  0.0      0     0 ?        S    22:58   0:00 [urdma_tx_thread
root      414  0.0  0.0      0     0 ?        S    22:58   0:00 [kworker/1:1]
root      419  0.0  0.0      0     0 ?        S    22:58   0:00 [kworker/0:2]
root      502  0.1  0.0      0     0 ?        S    22:58   0:00 [ubi_bgt0d]
root      503  0.0  0.0      0     0 ?        S<   22:58   0:00 [bioset]
root      508  0.0  0.0      0     0 ?        S<   22:58   0:00 [kworker/0:1H]
root      538  0.0  0.0      0     0 ?        S<   22:59   0:00 [kworker/1:1H]
root      551  0.0  0.0      0     0 ?        S    22:59   0:00 [ubifs_bgt0_2]
root      809  0.0  1.4   2144  1540 ?        S    22:59   0:00 /sbin/ubusd
root      812  0.0  1.8   3144  1924 ttyS0    Ss   22:59   0:00 /bin/ash --login
root      859  0.0  0.0      0     0 ?        S    22:59   0:00 [ubi_bgt1d]
root      885  0.0  0.0      0     0 ?        S    22:59   0:00 [ubifs_bgt1_0]
root      986  0.0  0.0      0     0 ?        S<   22:59   0:00 [bioset]
root      996  0.0  0.0      0     0 ?        S<   22:59   0:00 [cfg80211]
root     1003  0.0  0.0      0     0 ?        S    22:59   0:00 [kworker/u4:2]
root     1226  0.0  1.3   2320  1376 ?        S    22:59   0:00 /sbin/logd -S 64
root     1247  0.0  1.4   2780  1560 ?        S    22:59   0:00 /sbin/rpcd -s /v
root     1395  0.0  1.5   2396  1664 ?        S    22:59   0:00 /sbin/netifd
root     1888  0.0  1.3   2708  1416 ttyS0    R+   23:10   0:00 ps -aux

 发现一个状态为D的内核线程ehci_monitor

关于进程状态说明如下:

进程状态:
       O:进程正在处理器运行
       S:休眠状态(sleeping)
       R:等待运行(runable)R Running or runnable (on run queue) 进程处于运行或就绪状态
       I:空闲状态(idle)
       Z:僵尸状态(zombie)   
       T:跟踪状态(Traced)
       B:进程正在等待更多的内存页
       D:不可中断的深度睡眠

D状态标示不可中断,同时又是内核线程,说明该线程没有捕获任何信号,不能被中断,一直在CPU运行队列中 ,但是该线程又不占用CPU(前面cpu 100% idle),说明该线程没有在干活。此时我们可以认为,该线程的实现有点”问题“,不干活又一直要运行,可能是在等待什么条件或者检查什么状态亦或其他什么很机密的东西;总之,该线程的状态处理有待改善。

既然已经定位到了内核线程名,那么就没有什么比查看代码来得更直接的了,通过查看代码发现该线程就是在干一个活,总结起来就是每隔100ms查询一个条件,如下:

while(1)
{
if(check_status)
  do....
msleep(100);
}

该线程没有捕获任何信号,同时又没有改变运行状态,唯有一个msleep会引起调度,最终状态就是D,不可中断;

既然如此,我们来改善一下状态,做两个改变:

1. 设置线程状态为INTERRUPTIBLE

2. 使用schedule_timeout来显示的调度

while(1)
{

set_current_state(TASK_INTERRUPTIBLE);
if(check_status)
  do....
schedule_timeout(HZ)
}

 修改之后结果:

root@wireless-tag:/# uptime
 23:51:52 up 0 min,  0 users,  load average: 0.16, 0.05, 0.01
root@wireless-tag:/# ps -aux
USER      PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root        1  5.9  1.5   2596  1652 ?        Ss   23:51   0:02 /sbin/procd
root        2  0.0  0.0      0     0 ?        S    23:51   0:00 [kthreadd]
root        3  0.0  0.0      0     0 ?        S    23:51   0:00 [ksoftirqd/0]
root        4  0.0  0.0      0     0 ?        S    23:51   0:00 [kworker/0:0]
root        5  0.0  0.0      0     0 ?        S<   23:51   0:00 [kworker/0:0H]
root        6  0.0  0.0      0     0 ?        S    23:51   0:00 [kworker/u4:0]
root        7  0.0  0.0      0     0 ?        S    23:51   0:00 [rcu_preempt]
root        8  0.0  0.0      0     0 ?        S    23:51   0:00 [rcu_sched]
root        9  0.0  0.0      0     0 ?        S    23:51   0:00 [rcu_bh]
root       10  0.0  0.0      0     0 ?        S    23:51   0:00 [migration/0]
root       11  0.0  0.0      0     0 ?        S<   23:51   0:00 [lru-add-drain]
root       12  0.0  0.0      0     0 ?        S    23:51   0:00 [watchdog/0]
root       13  0.0  0.0      0     0 ?        S    23:51   0:00 [cpuhp/0]
root       14  0.0  0.0      0     0 ?        S    23:51   0:00 [cpuhp/1]
root       15  0.0  0.0      0     0 ?        S    23:51   0:00 [watchdog/1]
root       16  0.0  0.0      0     0 ?        S    23:51   0:00 [migration/1]
root       17  0.0  0.0      0     0 ?        S    23:51   0:00 [ksoftirqd/1]
root       18  0.0  0.0      0     0 ?        S    23:51   0:00 [kworker/1:0]
root       19  0.0  0.0      0     0 ?        S<   23:51   0:00 [kworker/1:0H]
root       20  2.0  0.0      0     0 ?        S    23:51   0:00 [kdevtmpfs]
root       21  0.0  0.0      0     0 ?        S<   23:51   0:00 [netns]
root       22  0.0  0.0      0     0 ?        S    23:51   0:00 [kworker/u4:1]
root      173  0.0  0.0      0     0 ?        S    23:51   0:00 [oom_reaper]
root      174  0.0  0.0      0     0 ?        S<   23:51   0:00 [writeback]
root      176  0.0  0.0      0     0 ?        S    23:51   0:00 [kcompactd0]
root      177  0.0  0.0      0     0 ?        S<   23:51   0:00 [crypto]
root      178  0.0  0.0      0     0 ?        S<   23:51   0:00 [bioset]
root      180  0.0  0.0      0     0 ?        S<   23:51   0:00 [kblockd]
root      201  0.0  0.0      0     0 ?        S<   23:51   0:00 [watchdogd]
root      282  1.3  0.0      0     0 ?        S    23:51   0:00 [kworker/0:1]
root      296  0.0  0.0      0     0 ?        S    23:51   0:00 [kswapd0]
root      297  0.0  0.0      0     0 ?        S<   23:51   0:00 [vmstat]
root      384  0.0  0.0      0     0 ?           23:51   0:00 [ehci_monitor]    ----> S态
root      400  0.0  0.0      0     0 ?        S    23:51   0:00 [urdma_tx_thread
root      414  0.5  0.0      0     0 ?        S    23:51   0:00 [kworker/1:1]
root      419  0.0  0.0      0     0 ?        S    23:51   0:00 [kworker/0:2]
root      422  0.0  0.0      0     0 ?        S<   23:51   0:00 [bioset]

 root@wireless-tag:/# vmstat -w 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        76568         3600        11308    0    0     0     0   51  103   4   6  90   0   0
 0  0            0        76568         3600        11308    0    0     0     0   56   57   0   0 100   0   0
 0  0            0        76584         3600        11308    0    0     0     0   43   56   0   0 100   0   0
 0  0            0        76584         3600        11308    0    0     0     0   43   53   0   0 100   0   0
 0  0            0        76584         3600        11308    0    0     0     0   44   59   0   0 100   0   0

结果显示很“完美”

关于内核线程的使用以及线程状态切换和维护,后面有时间再补充一篇博文,以便更强有力的说明CPU使用率和loadavg这两个参数的意义。

同时我们也能得出结论:CPU够不够用,系统压力大不大,不能单纯的只看使用率或者loadavg,需要两个相结合来分析。

这篇关于记最近Linux中遇到cpu使用率低loadavg高的分析过程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!