环境Centos 4.18.0-80.el8.x86_64
https://www.kernel.org/doc/Documentation/x86/kernel-stacks
int get_stack_info(unsigned long *stack, struct task_struct *task,
struct stack_info *info, unsigned long *visit_mask)
{
if (!stack)
goto unknown;
task = task ? : current;
if (in_task_stack(stack, task, info))
goto recursion_check;
if (task != current)
goto unknown;
if (in_exception_stack(stack, info))
goto recursion_check;
if (in_irq_stack(stack, info))
goto recursion_check;
if (in_entry_stack(stack, info))
goto recursion_check;
goto unknown;
}
从上述函数可以看出堆栈类型存在4种,在函数show_trace_log_lvl中有一段说明如下:
/*
* Iterate through the stacks, starting with the current stack pointer.
* Each stack has a pointer to the next one.
*
* x86-64 can have several stacks:
* - task stack
* - interrupt stack
* - HW exception stacks (double fault, nmi, debug, mce)
* - entry stack
*
* x86-32 can have up to four stacks:
* - task stack
* - softirq stack
* - hardirq stack
* - entry stack
*/
x86架构中一般用寄存器sp来存在栈指针。
| 类型 | 说明 |
|---|---|
| task_stack | 进程栈 stack_trace_save可导出进程栈 |
| exception_stack | 异常栈 |
| irq_stack | 中断栈,大小为IRQ_STACK_SIZE 16KB |
| entry_stack | 入口栈 |
在之前的文章也介绍过这个函数的作用,可以打印函数调用栈。
lib/dump_stack.c
/**
* dump_stack - dump the current task information and its stack trace
*
* Architectures can override this implementation by implementing its own.
*/
#ifdef CONFIG_SMP
static atomic_t dump_lock = ATOMIC_INIT(-1);
asmlinkage __visible void dump_stack(void)
{
unsigned long flags;
int was_locked;
int old;
int cpu;
/*
* Permit this cpu to perform nested stack dumps while serialising
* against other CPUs
*/
retry:
local_irq_save(flags);
cpu = smp_processor_id();
old = atomic_cmpxchg(&dump_lock, -1, cpu);
if (old == -1) {
was_locked = 0;
} else if (old == cpu) {
was_locked = 1;
} else {
local_irq_restore(flags);
cpu_relax();
goto retry;
}
__dump_stack();
if (!was_locked)
atomic_set(&dump_lock, -1);
local_irq_restore(flags);
}
|- dump_stack(); // lib/dump_stack.c
|- __dump_stack(); // arch/x86/kernel/dumpstack.c
|-