Linux系统下C程序如何实现CPU调用栈信息打印功能
Linux用户态C程序打印调用栈的可行方案
场景1:仅需要打印当前程序自身的调用栈
可以直接使用glibc内置的API实现用户态调用栈打印,效果和内核态dump_stack对应用户态部分的输出一致:
- 依赖头文件
<execinfo.h>,编译时需要加-rdynamic参数用于符号解析 - 示例实现代码:
#include <execinfo.h> #include <stdio.h> #include <stdlib.h> void print_call_stack(void) { void *stack_buf[128]; int stack_depth = backtrace(stack_buf, 128); char **sym_list = backtrace_symbols(stack_buf, stack_depth); if (sym_list == NULL) { perror("backtrace_symbols 调用失败"); return; } for (int i = 0; i < stack_depth; i++) { printf("%s\n", sym_list[i]); } free(sym_list); }
如果需要同时打印当前进程的内核态调用栈,可以直接读取/proc/self/stack文件的内容输出即可。
场景2:需要和echo t > /proc/sysrq-trigger输出一致的全系统进程/CPU内核态调用栈
你之前调用system报错是因为/proc/sysrq-trigger默认仅root用户有写权限,有两种解决路径:
- 路径1:提权运行你的程序,要么直接用root身份执行二进制文件,要么给二进制文件加对应能力:执行
setcap cap_sys_admin+ep /path/to/your/binary后,普通用户运行也可以正常写入sysrq触发文件 - 路径2:不需要触发sysrq,直接遍历
/proc下所有进程的stack文件,/proc/[pid]/stack存储的就是对应进程当前的内核态调用栈,输出格式和sysrq-t完全一致,普通用户可以读取自己启动的进程的栈信息,root可以读取所有进程的栈信息。
场景3:你编写的是内核模块需要打印栈
直接调用内核导出的dump_stack()函数即可,这个API本身就是内核态专属,用户态程序无法直接调用。
注意:如果需要解析内核函数的符号名称,需要安装对应内核版本的
kernel-debuginfo包,否则调用栈只会输出函数内存地址,不会显示函数名。
内容的提问来源于stack exchange,提问作者NotMe1993
相关产品推荐
相关产品推荐

