Linux INFO: rcu_sched self-detected stall on CPU

这篇具有很好参考价值的文章主要介绍了Linux INFO: rcu_sched self-detected stall on CPU。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

如果串口持续打印下面的信息,说明代码中出现了异常,程序一直占据了cpu不释放。cpu在调度中检测到了这种异常,在串口中打印出内核异常位置的调用栈。

这种检查内核缺省是打开的,CONFIG_RCU_CPU_STALL_TIMEOUT 参数是时间,如果cpu占据时间超过该参数,则会打印。在我调试的单板上缺省为60秒。

在openwrt系统上执行make kernel_menuconfig可以看到如下配置:

Linux INFO: rcu_sched self-detected stall on CPU,linux,运维,服务器

这种问题一般出现在内核程序出现了死循环的现象。因此通过调用栈信息很快能够找到程序的异常点。

[  814.604208] INFO: rcu_sched self-detected stall on CPU
[  814.614448]  0-...: (1 GPs behind) idle=0e6/140000000000002/0 softirq=1740/1755 fqs=36948
[  814.630874]   (t=78012 jiffies g=362 c=361 q=2868)
[  814.640399] NMI backtrace for cpu 0
[  814.647328] CPU: 0 PID: 1343 Comm: netifd Not tainted 4.14.195 #0
[  814.659436] Stack : 00000000 806a0000 00000000 800727ac 806d0000 80667b78 00000000 00000000
[  814.676060]         806299b8 87c09bec 87da631c 806a6a67 806247ac 00000001 87c09b90 53261622
[  814.692683]         00000000 00000000 80810000 00007000 00000000 00000192 00000007 00000000
[  814.709304]         00000000 806b0000 0009e0a0 00000000 80000000 806d0000 00000000 00000000
[  814.725925]         806ac5e0 806a40cc 000000e0 806a0000 00000000 802aa118 00000000 80810000
[  814.742548]         ...
[  814.747401] Call Trace:
[  814.752275] [<8000c7b0>] show_stack+0x58/0x100
[  814.761124] [<80540ca4>] dump_stack+0xa4/0xe0
[  814.769786] [<80547cc4>] nmi_cpu_backtrace+0xe4/0x108
[  814.779825] [<80547db0>] nmi_trigger_cpumask_backtrace+0xc8/0x168
[  814.791949] [<800874f8>] rcu_dump_cpu_stacks+0xc4/0x13c
[  814.802334] [<80086948>] rcu_check_callbacks+0x3b4/0x8b8
[  814.812896] [<8008a0b8>] update_process_times+0x34/0xdc
[  814.823299] [<8009b168>] tick_handle_periodic+0x34/0xd0
[  814.833693] [<8036c9a4>] gic_compare_interrupt+0x70/0x80
[  814.844257] [<8007a098>] handle_percpu_devid_irq+0xbc/0x1a8
[  814.855334] [<800742f0>] generic_handle_irq+0x40/0x58
[  814.865387] [<8025cd04>] gic_handle_local_int+0x9c/0xe8
[  814.875772] [<8025cec4>] gic_irq_dispatch+0x10/0x20
[  814.885465] [<800742f0>] generic_handle_irq+0x40/0x58
[  814.895521] [<8055eb8c>] do_IRQ+0x1c/0x2c
[  814.903484] [<8025c580>] plat_irq_dispatch+0xfc/0x138
[  814.913523] [<80007588>] except_vec_vi_end+0xb8/0xc4
[  814.923401] [<80033fb4>] irq_exit+0xac/0xc8
[  823.027079] mtk_soc_eth 1e100000.ethernet eth0: port 3 link down
[  827.873748] mtk_soc_eth 1e100000.ethernet eth0: port 3 link up
[  634.574208] INFO: rcu_sched self-detected stall on CPU
[  634.584461]  0-...: (1 GPs behind) idle=0e6/140000000000002/0 softirq=1740/1755 fqs=28760
[  634.600887]   (t=60009 jiffies g=362 c=361 q=2850)
[  634.610412] NMI backtrace for cpu 0
[  634.617342] CPU: 0 PID: 1343 Comm: netifd Not tainted 4.14.195 #0
[  634.629451] Stack : 00000000 806a0000 00000000 800727ac 806d0000 80667b78 00000000 00000000
[  634.646075]         806299b8 87c09bec 87da631c 806a6a67 806247ac 00000001 87c09b90 53261622
[  634.662698]         00000000 00000000 80810000 00006850 00000000 00000174 00000007 00000000
[  634.679319]         00000000 806b0000 00096b7e 00000000 80000000 806d0000 00000000 00000000
[  634.695940]         806ac5e0 806a40cc 000000e0 806a0000 00000000 802aa118 00000000 80810000
[  634.712562]         ...
[  634.717417] Call Trace:
[  634.722293] [<8000c7b0>] show_stack+0x58/0x100
[  634.731147] [<80540ca4>] dump_stack+0xa4/0xe0
[  634.739811] [<80547cc4>] nmi_cpu_backtrace+0xe4/0x108
[  634.749850] [<80547db0>] nmi_trigger_cpumask_backtrace+0xc8/0x168
[  634.761976] [<800874f8>] rcu_dump_cpu_stacks+0xc4/0x13c
[  634.772365] [<80086948>] rcu_check_callbacks+0x3b4/0x8b8
[  634.782933] [<8008a0b8>] update_process_times+0x34/0xdc
[  634.793340] [<8009b168>] tick_handle_periodic+0x34/0xd0
[  634.803735] [<8036c9a4>] gic_compare_interrupt+0x70/0x80
[  634.814303] [<8007a098>] handle_percpu_devid_irq+0xbc/0x1a8
[  634.825378] [<800742f0>] generic_handle_irq+0x40/0x58
[  634.835435] [<8025cd04>] gic_handle_local_int+0x9c/0xe8
[  634.845820] [<8025cec4>] gic_irq_dispatch+0x10/0x20
[  634.855513] [<800742f0>] generic_handle_irq+0x40/0x58
[  634.865572] [<8055eb8c>] do_IRQ+0x1c/0x2c
[  634.873537] [<8025c580>] plat_irq_dispatch+0xfc/0x138
[  634.883577] [<80007588>] except_vec_vi_end+0xb8/0xc4
[  634.893458] [<80033fb4>] irq_exit+0xac/0xc8

 官方网站上对RCU告警的解释如下:
https://www.kernel.org/doc/Documentation/RCU/stallwarn.txt

什么情况会打印RCU告警?

  • CPU在RCU的读逻辑里面循环;
  • CPU在关中断中循环;
  • CPU在关闭抢占的逻辑中循环;
  • CPU在禁用下半部循环的逻辑中循环;
  • 对于非抢占内核,可以在任何地方循环,且不需要调用schedule()函数,如果在内核中的循环是真正预期和理想的行为,您可能需要添加一些调用cond_resched()。

注:cond_resched() 的目的是显式请求当前任务进行调度。它在可以安全地主动让出处理器给其他任务的位置使用。函数 _cond_resched() 在 cond_resched() 内部调用,以执行实际的调度操作。

由于配置了内核态是不可抢占的,在内核态运行的程序可调用cond_resched主动让出cpu,是为了在不可抢占内核的一些耗时的内核处理路径中增加主动抢占点,防止其在内核态执行时间过长导致可能发生的soft lockup或者造成较大的调度延迟。

比如:对于非抢占式内核来说,在内核的很多地方,特别是文件系统(fs子系统)操作和内存管理(mm子系统)相关的一些耗时路径中,都已经被内核开发者识别出来,并使用cond_resched来减小延迟。

  • 如果通过串口连接去重启Linux系统,并且串口日志上打印启动时间。例如,使用115K的波特率连接串口,可能会来不及打印启动日志,进而导致RCU告警,特别是在添加了调试日志的时候,更容易出现;
  • 任何阻止RCU的宽限期k线程正常运行的东西。就会在控制台上报RCU stall的告警日志,此日志将包括k线程上一次运行的时间,以及下一次期望运行的时间。如果rcu线程饿死的话,还会打印额外的调试信息。

  • 在CONFIG_PREEMPT内核中的一个与cpu绑定的实时任务,这可能会碰巧在RCU中间抢占一个低优先级任务读端关键部分(一个高优先级的任务想要抢占一个低优先级任务,但是这个低优先级的任务正在进行RCU中的读操作)。这是尤其有害的,如果这个低优先级的任务不允许在任何其他CPU上运行,在这种情况下,下一个RCU宽限期永远无法完成,这一点最终会导致系统内存不足并挂起。当系统正在耗尽自身的过程中内存中,你可能会看到停止警告消息。

  • 在CONFIG_PREEMPT_RT内核中的一个受cpu绑定的实时任务,正在以比RCU软件线程更高的优先级运行。这将导致RCU回调永远不被调用,而在CONFIG_PREEMPT_RCU内核中则会进一步防止RCU宽限期。无论哪种方式系统最终会耗尽内存并挂起。在CONFIG_PREEMPT_RCU的案例中,你可能会看到RCU告警。(您可以使用rcutree.kthread_prio内核引导参数来增加RCU的k线程的调度优先级,这可以帮助避免这个问题。但是,请注意,这样做可能会增加系统的上下文切换速率,从而降低性能。)
  • 一种周期中断,其处理程序所花费的时间长于该时间连续的中断对之间的时间间隔。这可以

    防止RCU的k线程和软程序处理程序运行。请注意,例如,某些高开销的调试选项函数图跟踪器,会导致中断处理程序采取比正常情况要长得多,这反过来会导致RCU CPU失速警告。

  • 在快速系统上测试工作负载,调优失速警告超时到勉强避免RCU CPU停止警告,然后

    运行相同的工作负载和相同的停止警告超时缓慢的系统,在慢系统上可能就会报RCU告警。请注意,热节流器和按需调速器可以导致单个系统有时快,有时慢!

  • 硬件或软件问题会关闭调度程序时钟中断未处于动态空闲模式的CPU。这个问题真的发生了,而且似乎最有可能发生导致CONFIG_NO_HZ_COMMON=n内核的RCU CPU停止警告。

  • RCU实现中的一个bug。

  • 硬件故障。这是不太可能的,但已经发生了在现实生活中至少有一次。正在运行的系统中的CPU出现故障,失去反应,但不会立即造成崩溃。这最终导致了一系列的RCU CPU停止警告

    导致人们意识到CPU已经失败了。

  • RCU、RCU-sched和RCU-任务实现都有CPU停止警告。请注意,SRCU没有CPU停止警告。请注意RCU只在有一个宽限期时检测CPU暂停。没有宽限期,没有CPU停止警告。

  • 要诊断失速的原因,请检查堆栈跟踪。有问题函数通常会靠近堆栈的顶部。如果你在一个延长的摊位上有一系列的摊位警告,比较堆栈跟踪通常可以帮助确定停止的位置正在发生,它通常会在最近的顶部堆栈中从跟踪到跟踪保持相同的那部分。如果你能可靠地触发失速,ftrace(高效调试与分析:利用ftrace进行Linux内核追踪)就会很有帮助。

  • RCU的错误通常可以在CONFIG_RCU_TRACE的帮助下进行调试

    以及使用RCU的事件跟踪。有关RCU的事件跟踪的信息,请查看:

    参见包括/跟踪/事件/rcu.h。

RCU CPU停滞检测器调优

rcuupdate.rcu_cpu_stall_suppress模块参数禁用RCU的CPU失速检测器,它检测过度延迟RCU宽限期的条件。此模块参数在默认情况下支持CPU停止检测,但可以通过启动时参数或在运行时通过sysfs进行覆盖。

失速探测器对什么构成的概念过度延迟由一组内核配置变量和cpp宏控制:

CONFIG_RCU_CPU_STALL_TIMEOUT

此内核配置参数定义了该时间段RCU将从一个宽限期的开始开始等待,直到它发出RCU CPU停止警告。这个时间段通常是这样的21秒。

此配置参数可以在运行时通过以下属性进行更改 : /sys/module/rcupdate/parameters/rcu_cpu_stall_timeout,然而仅在循环开始时检查此参数。所以如果你在进入到RCU流程之后再修改这个参数,那么修改的值将不会影响本次循环的告警,只对下一次的检查生效。

RCU cpu stall警告消息可以通过修改下面变量的方式完全启用和禁用:

/sys/module/rcupdate/parameters/rcu_cpu_stall_suppress.

RCU_STALL_DELAY_DELTA

虽然锁闭装置非常有用,但它确实增加了些开销。因此,在CONFIG_PROVE_RCU条件下,在

打开RCU_STALL_DELAY_DELTA宏时,延时5秒钟发出RCU CPU停止警告消息。(这是一个cpp

宏,而不是内核配置参数。)

RCU_STALL_RAT_DELAY

CPU失速检测器试图使错误的CPU打印其自己的警告,因为这通常给提供质量更好的跟踪堆栈。

但是,如果有问题的CPU没有检测到它自己的失速在由RCU_STALL_RAT_DELAY指定的时间内,其他一些CPU也会抱怨。此延迟通常被设置为two jiffies。(这是一个cpp宏,而不是一个内核配置

参数)

rcupdate.rcu_task_stall_timeout

此boot/sysfs参数控制RCU任务失速警告间隔,零或小于0的值会抑制RCU-任务的停止

发出警告,正值设置失速警告间隔的秒数,RCU任务停止警告以以下行开始:

INFO: rcu_tasks detected stalls on tasks:

并继续输出每个任务的sched_show_task()任务停止当前RCU-task的宽限期。

解释RCU的CPU静态检测器和溢出器

对于非RCU任务类型的RCU,当CPU检测到它正在停止时,它将打印一个类似于以下内容的消息:

INFO: rcu_sched detected stalls on CPUs/tasks:
2-...: (3 GPs behind) idle=06c/0/0 softirq=1453/1455 fqs=0
16-...: (0 ticks this GP) idle=81c/0/0 softirq=764/764 fqs=0
(detected by 32, t=2603 jiffies, g=7075, q=625)

该消息表明CPU 32检测到CPU2和16都导致了CPU stall,并且停顿影响了RCU-sched。此消息之后通常会带有每个CPU的堆栈转储。请注意,PREEMPT_RCU抢占系统,可以被具体的task或CPU停滞,并打印出停滞的任务ID,比如“P3421”。甚至可能是task和cpu共同导致了rcu stall。

CPU 2's "(3 GPs(Grace Period) behind)":表示此CPU在过去三个宽限期内未与RCU核心交互。相比之下,CPU16(0表示此GP)表示该CPU在当前停滞的宽限期内没有进行任何调度时钟中断。

"idle=":打印dyntick空闲状态。

第一个"/"之前的十六进制数是低12位动态数计数器,如果CPU处于动态空闲模式,它将有一个偶数号的值,否则为奇数值。两个"/"之间的十六进制数是嵌套的值,如果在空闲循环中,它将是一个很小的非负数(如上所示),否则则是一个非常大的正数。

"softirq=":表示the stalled CPU已经执行的软中断的个数。第一个数字表示宽限期开始时启动后执行的数字,这可能是当前的(停止的)宽限期,也可能是较早的宽限期(例如,如果CPU可能在较长时间内处于动态空闲模式。第二个数字表示从启动开始当目前所执行的软中断的个数,如果此数字在打印RCU CPU stall告警的期间保持不变,那就说明此CPU已经无法再处理软中断了。这种情况可能是以下两种原因导致的:

1)stalled CPU关闭了中断,且一直自旋;

2)在实时内核中,高优先级的进程占用的CPU,RCU软中断处理函数正在被饿死。

"fqs=":显示了CPU被强制休眠的次数。
"detected by":表示是哪个CPU检测到停顿(上面的日志中显示的是CPU 32),自宽限期开始以来已经经过了多少次jiffies(上面的日志为2603),宽限期序号(7075),并估算所有CPU中排队的RCU回调总数(在这种情况下为625)。

在具有CONFIG_RCU_FAST_NO_HZ的内核中,将为每个CPU打印更多信息:
0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 softirq=82/543 last_accelerate: a345/d342 nonlazy_posted: 25 .D

信息: rcu_tasks检测到任务上的停止:

并继续输出每个任务的sched_show_task()

任务停止当前RCU-任务的宽限期。文章来源地址https://www.toymoban.com/news/detail-644912.html

到了这里,关于Linux INFO: rcu_sched self-detected stall on CPU的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux 内核源码分析】RCU机制

    Linux内核的RCU(Read-Copy-Update)机制是一种用于实现高效读取和并发更新数据结构的同步机制。它在保证读操作不被阻塞的同时,也能够保证数据的一致性。 RCU的核心思想是通过延迟资源释放来实现无锁读取,并且避免了传统锁带来的争用和开销。具体而言,RCU维护了一个“回

    2024年01月15日
    浏览(74)
  • Linux内核源码分析 (6)RCU机制及内存优化屏障

    问题: RCU 英文全称为 Read-Copy-Update ,顾名思义就是 读-拷贝-更新 ,是 Linux 内核中重要的同步机制。 Linux 内核已有原子操作、读写信号量等锁机制,为什么要单独设计一个比较复杂的新机制? RCU的原理 RCU记录所有指向共享数据的指针的使用者,当要修改该共享数据时,首先

    2024年02月10日
    浏览(57)
  • 【安全】查杀linux隐藏挖矿病毒rcu_tasked

    这是黑客使用的批量蔓延病毒的工具,通过如下脚本 /root/.cfg/目录下的病毒源文件 目前未查清楚原文件是通过隐藏在什么程序中带过来的,这是一大遗憾 中毒现象提现未cpu占用100%,且通过top、netstat、ps等命令找不到进程号 挖矿的矿池IP,全是国外的IP,大概看了一下,基本

    2024年04月15日
    浏览(39)
  • 解决实际项目中stalled时间过久的问题

    在公司参与了一个做度量统计的项目,该项目的特点是页面上的表格、卡片、图标非常多。项目经常出现一种情况:页面加载速度较慢,开始怀疑是由于计算量较大,后端接口相应速度较慢。优化了一版后端接口后(加缓存、优化SQL),发现有时接口的相应速度还是很慢,有

    2023年04月22日
    浏览(43)
  • Linux Kernel:thread_info与进程调度

    环境: Kernel Version:Linux-5.10 ARCH:ARM64      一:概述 Linux是多任务系统,它支持(看上去)并发执行的若干进程。系统中同时真正在运行的进程数目最多不超过CPU数目,因此内核会按照短的时间间隔在不同的进程之间切换(用户是注意不到的),这样就造成了同时处理多进

    2024年02月08日
    浏览(61)
  • Linux多线程编程- pthread_self()

    pthread_self() 函数是 POSIX 线程库的一部分,它提供了一个非常简单的功能:获取当前线程的唯一标识符。这个标识符是 pthread_t 类型的,通常是一个无符号的长整型值,不过具体的类型是由实现定义的,这意味着它可以在不同的操作系统上有不同的表示。 这个标识符对于调试多

    2024年02月06日
    浏览(33)
  • Linux 使用TCP_INFO查询TCP连接的状态信息

    Linux 上可以使用TCP_INFO查询TCP连接状态信息包括: 发送方拥塞窗口阈值、发送方缓冲区拥塞窗口、advmss(Advertised MSS)、通过 ACK 确认的累计字节数等等 1. `__u8 tcpi_state;`:表示 TCP 连接的状态。 2. `__u8 tcpi_ca_state;`:表示 TCP 拥塞控制状态。 3. `__u8 tcpi_retransmits;`:表示已经重传

    2024年02月10日
    浏览(40)
  • Linux 内核动态打印调试(dev_info、 dev_dbg )

    目录 前言 1 printk消息级别 2 调整内核printk打印级别  3 dev_xxx函数简介 4 配置内核使用动态打印 5 动态调试使用方法 6 动态打印调试的基本原理  🎈个人主页🎈:linux_嵌入式大师之路的博客-CSDN博客 🎉🎉🎉欢迎 👍点赞✍评论⭐收藏 🤝希望本文能对你有所帮助,欢迎在评论

    2024年02月10日
    浏览(47)
  • RCU安全引用计数

    原文网址:https://lwn.net/Articles/93617 原文作者:Corbet 原文时间:2004年7月14日 内核提供了一种用于实现引用计数的简单机制kref;该机制是今年3月份完成的。kref机制的核心思想是,提供支持原子操作的计数器,用于对未决引用【outstanding references】进行计数。如果计数器数值为

    2024年02月11日
    浏览(41)
  • RCU501 RMP201-8 KONGSBERG 分布式处理单元

    RCU501  RMP201-8 KONGSBERG 分布式处理单元 AutoChief®600使用直接安装在主机接线盒中的分布式处理单元。进出发动机的所有信号都在双冗余CAN线路(发动机总线)上传输。 所有不重要的传感器都可以与K-Chief 600报警和监控系统共享,只需要一个主机接口。这一原则大大降低了安装和布

    2024年02月09日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包