Linux内核可能导致RCU stall的原因

1.关于RCU
RCU(Read-Copy Update) 是 Linux 2.6 内核开始引入的一种新的锁机制,与 spinlock 、rwlock 不同,RCU 有其独到之处,它只适用于读多写少的情况。
RCU是基于其原理命名的,Read-Copy Update ,[Read]指的是对于被 RCU 保护的共享数据,reader 可以直接访问,不需要获得任何锁;[Copy Update]指的是 writer 修改数据前首先拷贝一个副本,然后在副本上进行修改,修改完毕后向 reclaimer (垃圾回收器)注册一个回调函数(callback),在适当的时机完成真正的修改操作–把原数据的指针重新指向新的被修改的数据,–这里所说的适当的时机就是当既有的 reader 全都退出临界区的时候,而等待恰当时机的过程被称为grace period 。在RCU机制中,writer 不需要和 reader 竞争任何锁,只在有多个 writer 的情况下它们之间需要某种锁进行同步作,如果写操作频繁的话RCU的性能会严重下降,所以RCU只适用于读多写少的情况。

2.RCU stall
GP 是 RCU 实现 reader 和 writer 同步的关键,而它的长度取决于 reader 临界区的执行时间。 如果其中某个 reader 在临界区中陷入了死循环,那么 GP 就无法结束,形成 RCU Stall 。针对这种情况,内核提供了一套 debug 机制,可以在检测到 CPU stall 后报告 warning ,产生 stack dump trace,以辅助调试和分析。但对于一些嵌入式工程来说,仅仅报告 warning 显然是不够的,因此有些工程中会让发生 RCU Stall 时直接调用 bug() 函数或者 panic() 函数直接让系统死机。

3.以下问题可能导致 RCU stall:
o 在 RCU 读取端临界区中循环的 CPU。
o 禁用中断的 CPU 循环。这种情况会导致 RCU-sched 和 RCU-bh 停止。
o 禁用抢占的 CPU 循环。这种情况会导致 RCU-sched 停顿,如果 ksoftirqd 正在使用,RCU-bh 会停顿。
o 禁用下半部分的 CPU 循环。这种情况会导致 RCU-sched 和 RCU-bh 停止。
o 对于 !CONFIG_PREEMPT 内核,CPU 在内核中的任何位置循环而不调用 schedule()。请注意 cond_resched() 不一定能防止 RCU CPU 停顿警告。因此,如果内核中的循环确实是预期的和合意的行为,您可能需要将一些 cond_resched() 调用替换为对 cond_resched_rcu_qs() 的调用。
o 使用太慢的控制台连接引导 Linux,无法跟上引导时控制台消息的速度。例如,115Kbaud 串行控制台可能太慢,无法跟上启动时消息速率,并且会经常导致 RCU CPU 停顿警告消息。特别是如果您添加了调试 printk()s。
o 任何阻止 RCU 的宽限期 kthread 运行的东西。这可能会导致“所有 QSes seen”控制台日志消息。此消息将包含有关 kthread 上次运行时间以及预期运行频率的信息。
o CONFIG_PREEMPT 内核中的 CPU 绑定实时任务,它可能会在 RCU 读取端临界区的中间抢占低优先级任务。如果不允许该低优先级任务在任何其他 CPU 上运行,这尤其具有破坏性,在这种情况下,下一个 RCU 宽限期将永远无法完成,最终将导致系统内存不足并挂起。当系统正在运行自己的内存不足时,您可能会看到停顿警告消息。
o CONFIG_PREEMPT_RT 内核中的 CPU 绑定实时任务,其运行的优先级高于 RCU 软中断线程。这将阻止 RCU 回调被调用,并且在 CONFIG_PREEMPT_RCU 内核中将进一步阻止 RCU 宽限期完成。无论哪种方式,系统最终都会耗尽内存并挂起。在 CONFIG_PREEMPT_RCU 情况下,您可能会看到停顿警告消息。
o 硬件或软件问题关闭了未处于 dyntick-idle 模式的 CPU 上的调度程序时钟中断。这个问题确实发生了,并且似乎最有可能导致 CONFIG_NO_HZ_COMMON=n 内核的 RCU CPU 停顿警告。
o RCU 实现中的一个错误。
o 硬件故障。这不太可能发生,但在现实生活中至少发生过一次。正在运行的系统中的 CPU 发生故障,变得无响应,但不会导致立即崩溃。这导致了一系列 RCU CPU 停顿警告,最终导致人们意识到 CPU 发生了故障。

如果遇到RCU问题可以开启 menuconfig 中以下的一些宏为 RCU 启用跟踪,正如第2部分对RCU stall的介绍,某个 reader 在临界区中陷入了死循环的话,可能会发生softkockup导致发生RCU stall,因此我们在做 RCU stall 排查的时候通常也会开启lock debug相关的宏。
在这里插入图片描述

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RCU(Read-Copy Update)是 Linux 内核中一种用于实现读者优化的机制,它可以提供高效的读访问,同时保证写操作的一致性。RCU stallRCU停滞)是指在某些情况下,RCU 的正常执行被延迟或阻塞,导致系统性能下降或出现延迟。 以下是一些可能导致 RCU stall 发生的场景: 1. 大量的内核线程:当系统中运行大量的内核线程时,这些线程可能会争夺 CPU 资源,导致 RCU stall。这可能发生在一些密集型的内核工作负载下,例如高网络负载或大量的设备驱动程序。 2. 长时间的自旋锁持有:如果某个内核线程持有自旋锁,并且在尝试获得该自旋锁时发生了阻塞,那么其他依赖该自旋锁的 RCU 读取程序可能会被阻塞,导致 RCU stall。这种情况通常发生在某个内核线程长时间占用自旋锁的情况下。 3. 中断关闭时间过长:当中断被禁止并且保持关闭状态的时间过长时,可能导致 RCU stall。这是因为 RCU 读取程序需要在中断上下文中执行,如果中断关闭时间过长,RCU 读取程序可能无法及时执行。 4. 内核线程优先级过高:如果某个内核线程的优先级设置过高,它可能会长时间占用 CPU 资源,从而导致其他依赖于 RCU 的线程无法及时执行,引发 RCU stall。 5. 调度不公平:如果系统中某些进程或线程的调度不公平,例如某些进程占用了大量的 CPU 时间,那么其他进程或线程可能会受到影响,包括 RCU 读取程序,从而导致 RCU stall。 6. 内存压力:当系统内存不足时,可能会触发内存回收机制,例如缺页中断或页面换入/换出操作。这些操作可能导致 RCU stall,因为 RCU 读取程序需要访问内存来读取数据。 请注意,以上场景只是可能导致 RCU stall 发生的一些示例。实际情况可能因系统配置、硬件和软件环境等因素而有所不同。在诊断和解决 RCU stall 问题时,通常需要使用性能分析工具和内核跟踪工具来识别具体的瓶颈和原因
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值