方法一:可以通过/proc/线程ID/stack来获取指定线程当前的调用栈,但是该方案存在限制:可能不能准确获取出问题的时候该线程的调用栈
方法二:通过内核接口save_stack_trace_tsk和%pS,在程序检测到异常的时候打印出对应的调用栈用于问题定位,具体的方法(从内核/proc文件系统处理打印调用栈的proc_pid_stack中简单修改而来):
static int kprink_stack(struct task_struct *task)
{
struct stack_trace trace;
unsigned long *entries;
int err;
entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL);
if (!entries)
return -ENOMEM;
trace.nr_entries = 0;/*调用返回后,为记录的调用栈中的有效符号的个数*/
trace.max_entries = MAX_STACK_TRACE_DEPTH;/*传入的trace.entries的大小,save_stack_trace_tsk最多保持该数量的调用栈符号*/
trace.entries = entries;/*返回的符号地址保存在这里*/
trace.skip = 0;/*从调用栈的顶开始,忽略的调用栈符号数量*/
err = lock_trace(task);
if (!err) {
save_stack_trace_tsk(task, &trace);
for (i = 0; i < trace.nr_entries; i++) {
printk(m, "[<%pK>] %pS\n",
(void *)entries[i], (void *)entries[i]);
}
unlock_trace(task);
}
kfree(entries);
return err;
}
说明:其中的%pS用于打印内核符号,内核的相关处理见printk--->vprintk--->vscnprintf-->vsnprintf-->symbol_string的处理