为啥“echo l > /proc/sysrq-trigger”调用跟踪输出总是相似?

Posted

技术标签:

【中文标题】为啥“echo l > /proc/sysrq-trigger”调用跟踪输出总是相似?【英文标题】:Why is "echo l > /proc/sysrq-trigger" call trace output always similar?为什么“echo l > /proc/sysrq-trigger”调用跟踪输出总是相似? 【发布时间】:2015-07-15 14:00:57 【问题描述】:

根据the official kernel.org documentation echo l > /proc/sysrq-trigger 应该给我所有CPU的当前调用跟踪。但是当我这样做几次并查看dmesg 之后,呼叫跟踪看起来完全相似。这是为什么呢?

【问题讨论】:

可能是OT,我不认为这是一个编程问题。可能会尝试服务器故障。 您每次都在执行完全相同的操作:触发 sysrq。所以回溯只是向你展示了这个事实。尝试使用 diff 工具比较两个不同调用 (echo l > /proc/sysrq-trigger) 的回溯,您会发现它们有不同的堆栈、寄存器值等。如果您向我们展示您拥有的实际回溯会更好。跨度> @BadZen 不,这对我来说似乎不是题外话。这个问题暗示了一些关于内核内部的知识。 @Ian 那是因为他的 CPU 负载很高。在您的情况下,您的 CPU #0 回溯显示它正在执行您的 sysrq 命令(write_sysrq_trigger() 函数),而 CPU #1 回溯显示它处于 IDLE 状态(cpuidle_enter_state() 函数)。尝试非常密集地加载系统,然后执行 sysrq 命令以获取新的回溯。您会看到一个 CPU 正在执行您的 sysrq 命令,而第二个 CPU 不再处于空闲状态,而是在做一些实际的工作。 @Ian 我将我的 cmets 移至实际答案。它也有你在 cmets 中最后一个问题的答案。 【参考方案1】:

同样的回溯解释

在您的情况下,您的 CPU #0 回溯显示它正在执行您的 sysrq 命令(由 write_sysrq_trigger() 函数判断):

delay_tsc+0x1f/0x70
arch_trigger_all_cpu_backtrace+0x10a/0x140
__handle_sysrq+0xfc/0x160
write_sysrq_trigger+0x2b/0x30
proc_reg_write+0x39/0x70
vfs_write+0xb2/0x1f0
SyS_write+0x42/0xa0
system_call_fast_compare_end+0x10/0x15

并且 CPU #1 回溯显示它处于 IDLE 状态(由cpuidle_enter_state() 函数判断):

cpuidle_enter_state+0x40/0xc0
cpu_startup_entry+0x2f8/0x400
start_secondary+0x20f/0x2d0

尝试非常密集地加载您的系统,然后执行您的 sysrq 命令以获取新的回溯。您会看到一个 CPU 正在执行您的 sysrq 命令,而第二个 CPU 不再处于空闲状态,而是在做一些实际的工作。

用户空间回溯

至于内核回溯中的用户空间函数:尽管system call 代表用户空间进程(在内核空间中)执行(请参阅 CPU0 的回溯中的Comm: bash),但它是不可能的 使用标准内核回溯机制(在dump_stack() 函数中实现)打印用户空间进程回溯。问题在于内核堆栈不包含任何用户空间进程调用(这就是为什么您只能在回溯中看到内核函数)。

用户空间进程调用可以在相应进程的用户空间堆栈中找到。为此,我建议您使用OProfile profiler。当然,它只会给你一个二进制堆栈。为了获得实际的函数名称,您需要向 gdb 提供符号信息。

详情:

[1]kernel stack and user-space stack

[2]how to dump kernel stack in syscall

[3]How to print the userspace stack trace in linux kernelspace

【讨论】:

以上是关于为啥“echo l > /proc/sysrq-trigger”调用跟踪输出总是相似?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?