Linux内核栈和中断栈

内核栈


#define MIN_THREAD_SHIFT    (14 + KASAN_THREAD_SHIFT)
#define THREAD_SIZE     (UL(1) << THREAD_SHIFT)

union thread_union {
#ifndef CONFIG_THREAD_INFO_IN_TASK
    struct thread_info thread_info;
#endif
    unsigned long stack[THREAD_SIZE/sizeof(long)];
};

注意这里有一个宏来区分stack的实现方式 CONFIG_THREAD_INFO_IN_TASK ,如果定义了该宏,实际上会通过动态申请物理页来作为stack,并且把stack放到 task_struct 结构体中,用 task_struct->stack 来表示。

中断栈

  • 对于x86平台:

x86平台上,中断栈是独立于内核栈的存在,两者并不共享,如果是多处理器架构,那么每个CPU都对应有一个中断栈,本文不对x86做介绍。

  • 对于 ARM平台:

中断栈和内核栈则是共享的,中断栈和内核栈共享有一个负面因素,如果中断发生嵌套,可能会造成栈溢出,从而可能会破坏到内核栈的一些重要数据。

  • 对于ARM64平台:

中断栈的实现是独立的,并且区分两种情况,分别是vmap申请内存,还是直接静态定义,并且根据CPU个数,每个CPU对应单独的一个stack。


arch/arm64/kernel/irq.c:

#ifdef CONFIG_VMAP_STACK

static void init_irq_stacks(void)

{

    int cpu;

    unsigned long *p;



    for_each_possible_cpu(cpu) {

        /*

        * To ensure that VMAP'd stack overflow detection works

        * correctly, the IRQ stacks need to have the same

        * alignment as other stacks.

        */

        p = __vmalloc_node_range(IRQ_STACK_SIZE, THREAD_ALIGN,

                     VMALLOC_START, VMALLOC_END,

                     THREADINFO_GFP, PAGE_KERNEL,

                     0, cpu_to_node(cpu),

                     __builtin_return_address(0));



        per_cpu(irq_stack_ptr, cpu) = p;

    }

}

#else

/* irq stack only needs to be 16 byte aligned - not IRQ_STACK_SIZE aligned. */

DEFINE_PER_CPU_ALIGNED(unsigned long [IRQ_STACK_SIZE/sizeof(long)], irq_stack);



static void init_irq_stacks(void)

{

    int cpu;



    for_each_possible_cpu(cpu)

        per_cpu(irq_stack_ptr, cpu) = per_cpu(irq_stack, cpu);

}

#endif

你可能感兴趣的:(内核笔记)