整体介绍
最近从linux源码,深入的理解一下linux栈的结构,先上图看一下整体结构
Thread_info 在这里的存储方式是,从低地址到高地址存储的,thread_info 结构的最后一个成
员是存储在 stack_end_magic 前面的(地址从低向高来看)。这个结构不适用于 0 号进程,因为 0 号进程是系统启动的时候手动填充的,它没有 magic
number,没有顶端的 pt_regs。
0号进程的创建
arch/arm/kernel/head.S 文件中开始了 kernel 的旅程,也是第一个进程是如何来的。下面分析代码。
* This is normally called from the decompressor code. The requirements
* are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
* r1 = machine nr, r2 = atags or dtb pointer.
从 ENTRY(stext)开始,kernel 开始为启动进行一系列准备工作,即 kernel 启动需要的条件。在创建完页表之后,将__mmap_switched 放到 R13 寄存器中,如下,这个函数(__mmap_switched)是以后创建第一个进程的地方。
.arm
__HEAD
....
bl __vet_atags
#ifdef CONFIG_SMP_ON_UP
bl __fixup_smp
#endif
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
bl __fixup_pv_table
#endif
bl __create_page_tables
/*
* The following calls CPU specific code in a position independent
* manner. See arch/arm/mm/proc-*.S for details. r10 = base of
* xxx_proc_info structure selected by __lookup_processor_type
* above. On return, the CPU will be ready for the MMU to be
* turned on, and r0 will hold the CPU control register value.
*/
ldr r13, =__mmap_switched @ address to jump to after
@ mmu has been enabled
adr lr, BSYM(1f) @ return (PIC) address
mov r8, r4 @ set TTBR1 to swapper_pg_dir
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
THUMB( mov pc, r12 )
1: b __enable_mmu
ENDPROC(stext)
__mmap_switched 是在 mmu enable 之后才执行的。根据代码,它应该是由
__enable_mmu 调用执行的。__enable_mmu 执行完后会导致如下结果
/*
* Setup common bits before finally enabling the MMU. Essentially
* this is just loading the page table pointer and domain access
* registers.
*
* r0 = cp#15 control register
* r1 = machine ID
* r2 = atags or dtb pointer
* r4 = page table pointer
* r9 = processor ID
* r13 = *virtual* address to jump to upon completion
*/
__enable_mmu:
......
b __turn_mmu_on
ENDPROC(__enable_mmu)
在跳转到__turn_mmu_on 之前执行的都是对 r0,r1 等寄存器的加载。这个函数将真正的 enable
mmu。
/*
* Enable the MMU. This completely changes the structure of the visible
* memory space. You will not be able to trace execution throug