top始终显示load 1

观察到一个奇怪的现象,同样的Raspberry Pi 4,区别是一个Pi4是2G版本,使用TF卡;另一个Pi4是8G版本,直接使用外接的SSD移动硬盘。 两个树莓派都是使用Ubuntu 20.04 for Raspberry Pi 64bit版本,操作系统原先是安装在TF卡,然后通过dd命令clone到另一个使用SSD移动硬盘的树莓派。

照理说两个系统应该完全一致,但是发现还是有点差异

  • 8G版本,可以连接无线访问internet,我发现这个主机始终有一个负载Load 1存在,但是,却看不到运行的进程,系统进程基本都是sleep的

top - 22:54:18 up 1 day,  5:02,  2 users,  load average: 1.00, 1.00, 1.00
Tasks: 129 total,   1 running, 128 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.1 us,  0.1 sy,  0.0 ni, 99.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   7810.3 total,   7246.5 free,    173.0 used,    390.8 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   7522.3 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   4079 ubuntu    20   0   10700   3176   2720 R   0.7   0.0   0:00.15 top
   3852 root      20   0       0      0      0 I   0.3   0.0   0:00.10 [kworker/0:1-events]
      1 root      20   0  167624  10796   7336 S   0.0   0.1   0:06.50 /sbin/init fixrtc
      2 root      20   0       0      0      0 S   0.0   0.0   0:00.06 [kthreadd]
      3 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 [rcu_gp]
      4 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 [rcu_par_gp]
      6 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 [kworker/0:0H-kblockd]
      8 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 [mm_percpu_wq]
      9 root      20   0       0      0      0 S   0.0   0.0   0:00.08 [ksoftirqd/0]
     10 root      20   0       0      0      0 I   0.0   0.0   0:02.40 [rcu_preempt]
     11 root      rt   0       0      0      0 S   0.0   0.0   0:00.60 [migration/0]
     12 root     -51   0       0      0      0 S   0.0   0.0   0:00.00 [idle_inject/0]
     14 root      20   0       0      0      0 S   0.0   0.0   0:00.00 [cpuhp/0]
     15 root      20   0       0      0      0 S   0.0   0.0   0:00.00 [cpuhp/1]
     16 root     -51   0       0      0      0 S   0.0   0.0   0:00.00 [idle_inject/1]
     17 root      rt   0       0      0      0 S   0.0   0.0   0:00.60 [migration/1]
     18 root      20   0       0      0      0 S   0.0   0.0   0:01.06 [ksoftirqd/1]
     20 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 [kworker/1:0H-kblockd]
     21 root      20   0       0      0      0 S   0.0   0.0   0:00.00 [cpuhp/2]
     22 root     -51   0       0      0      0 S   0.0   0.0   0:00.00 [idle_inject/2]
     23 root      rt   0       0      0      0 S   0.0   0.0   0:00.60 [migration/2]
     24 root      20   0       0      0      0 S   0.0   0.0   0:00.04 [ksoftirqd/2]
     26 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 [kworker/2:0H-kblockd]
     27 root      20   0       0      0      0 S   0.0   0.0   0:00.00 [cpuhp/3]
     28 root     -51   0       0      0      0 S   0.0   0.0   0:00.00 [idle_inject/3]
     29 root      rt   0       0      0      0 S   0.0   0.0   0:00.58 [migration/3]
     30 root      20   0       0      0      0 S   0.0   0.0   0:00.05 [ksoftirqd/3]
     32 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 [kworker/3:0H-kblockd]
     33 root      20   0       0      0      0 S   0.0   0.0   0:00.04 [kdevtmpfs]
     34 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 [netns]
     35 root      20   0       0      0      0 S   0.0   0.0   0:00.00 [rcu_tasks_kthre]
     36 root      20   0       0      0      0 S   0.0   0.0   0:00.00 [kauditd]
     38 root      20   0       0      0      0 S   0.0   0.0   0:00.05 [khungtaskd]
  • 2G版本,暂时不能连接无线访问internet,则系统负载接近0

我比较奇怪,这个Load 1到底是什么原因导致的,为何看不到运行进程,也没有看到有读写磁盘的iowait。

Load概念

虽然我们都知道在Linux上top命令显示的Load是一个统计数据,表明队列中有多少进程,通常有多少运行的进程占用cpu资源或者iowait,就会显示在Load上。但是,我们很少会仔细研究这个Load的计算方法,只知道这个值不能高于CPU核心数量,超出则表明系统负载过高。

做一个简单的比喻(假设你是一座大桥的交通调度员):

  • 对于一个单核心处理器就类似多通道高速路的一条通道

  • 假设大桥的一个通道能够摆满6台汽车依次通过,则当桥上的一个通告有3台车,则负载就是 0.5(3/6=0.5));如果一个通道有8台车,则有2辆车排在桥通道外面,则负载就是(8/6=1.7)

  • 对于多处理器,相当于有多条车道,则原先一个通道只能承载6辆车,多出的2辆车现在不需要堆积在桥外,可以从其他通道通过。所以对于多处理器,高于1.0的负载也不需要担心。

理解Load Average

排查

回到我们现在的问题,我们看到top显示并没有运行的进程,那么占用top中的Load是什么呢?

实际上Load计算不仅包含了运行进程,也包含了等待CPU资源的进程,例如一个进程在等待IO - 磁盘或者网络。

  • 通过 ps -e v 命令可以检查进程状态

需要注意我们输出中进程是 RD 状态的,就是影响负载的进程。

  • cat /proc/loadavg 可以查看当前负载:

注意,Load Average是只在运行队列和等待IO的任务数量。

  • 过滤出RD 状态进程

输出可以看到有一个D住进程

为什么有一个 kworker 出现了D?

查看这个进程堆栈可以看到,是存在io等待,但是这个io等待是位于 mmc 也就是在等待SD卡设备

原因是我配置了从外接USB存储设备启动,但是eeprom配置启动顺序是先TF卡后USB设备,启动时我确实看到屏幕闪过mmc超时,可能是这个原因导致有内核进程始终在等待mmc返回信息(但是没有SD卡)。

为了测试验证这个问题是偶发还是一直存在,我先重启一次系统,看看这个问题是否消除。果然,重启发现系统依然负载是1,依然是同样的进程D住:

注意到D住的进程号会变化,有时候是168,过一会再检查D住的是100,其中100的D住进程和重启前检查一样,是有关mmc的

进程100如下:

上述这个问题是因为我配置了 树莓派4 USB启动Ubuntu Server 20.04 ,当前epprom通过USB存储启动依然会先读取SD卡,如果SD卡不存在,就会导致系统内核进程始终D住。这个问题,我暂时通过配置仅从USB外接存储启动来规避。

参考

Last updated

Was this helpful?