单片机
返回首页

OK6410A 开发板 (八) 119 linux-5.11 OK6410A arm-linux的栈

2022-08-09 来源:csdn

硬件上:

armv6 有 6个 R13

R13_usr 和 R13_sys 是同一个

还有 R13_svc R13_abt R13_und R13_irq R13_fiq


软件上

linux boot时有一个栈

linux 各种异常处理有栈(5个异常模式,1个system模式)

对应多少个栈?

svc mode 对应每个进程有一个栈?

irq mode 是固定的栈?

abort 呢? und 呢 ? fiq 呢?

system mode 呢?

linux 在 user mode 时 有栈 , (应用程序的栈,每个应用程序有一个栈,有N个应用程序)


boot的栈不管,没啥意思

从线程和异常来说事

1. 线程分类

2. 异常分类


每个线程有两个栈,一个内核(svc)栈,一个用户栈。

异常时,有临时栈(12字节)(irq und abt fiq),然后有长期栈(svc,即用户的内核栈)


临时栈

临时栈的地址及大小

地址 : 位于 全局变量 static struct stack stacks[NR_CPUS]; 中

大小 :12 字节


BOOT过程

boot时的栈

boot栈的地址及大小

地址 : init_stack  - init_stack+0x1000

大小 : 4KB


从stext到start_kernel , 没用栈???

从start_kernel 开始, 走在 svc mode???,

start_kernel 运行时的栈, 是 链接出来的(和init_stack 有关),4KB大小

https://blog.csdn.net/u011011827/article/details/116056620


线程分类

idle 内核线程的一个内核栈

内核栈的地址及大小


栈位置: X - X+0x2000 // 'slab task_struct' 中的 stack成员的值为X

栈大小: 8KB


idle 进程的 TCB 分成了 两块

struct task_struct init_task

void                *stack; // 用于存放 对应的 thread_info 的 地址

struct thread_info init_thread_info

.task       = &init_task // 对于存放 对应的 task_struct  的地址


栈位置: slab task_struct 中的 stack成员的值为栈顶X(X->X+STACK_SIZE为整个栈)

栈大小: 由 arch/arm/include/asm/thread_info.h 中的 THREAD_SIZE 决定 // 8KB 或者16KB

// CONFIG_KASAN=n : 8KB

// CONFIG_KASAN=y : 16KB


init 内核线程的一个内核栈及init用户线程的一个用户栈和内核栈

内核栈的地址及大小

栈位置: X - X+0x2000 // 'slab task_struct' 中的 stack成员的值为X

栈大小: 8KB


用户栈的地址及大小

栈位置: 0xBE80 0000 - 0xBF00 0000

栈大小: 8MB


用户栈的伸缩对于应用程序来说是透明的,应用程序不需要自己去管理栈,这是操作系统提供的功能。


应用程序在刚刚启动的时候(由fork()系统调用复制出新的进程),新的进程其实并不占有任何栈的空间。


当应用程序中调用了函数需要压栈时,会触发一个page fault,内核在处理这个异常里会发现进程需要新的栈空间,于是建立新的VMA并映射内存给用户栈


https://www.tiehichi.site/2020/10/22/Linux%E8%BF%9B%E7%A8%8B%E6%A0%88%E7%A9%BA%E9%97%B4%E5%A4%A7%E5%B0%8F/

栈位置: 0xC0000000-0x01000000 ( 最高处)

load_elf_binary

retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), executable_stack);


#define CONFIG_PAGE_OFFSET 0xC0000000

#define SZ_16M              0x01000000

#define TASK_SIZE       (UL(CONFIG_PAGE_OFFSET) - UL(SZ_16M))

#define TASK_SIZE_26        (UL(1) << 26)

#define STACK_TOP   ((current->personality & ADDR_LIMIT_32BIT) ? TASK_SIZE : TASK_SIZE_26)



栈位置: 0xC0000000-0x01000000 ( 最高处)


栈大小: 8MB

ulimit -a看到系统对当前进程的栈size进行了限制,大部分是8M的限制

ulimit -s来修改栈的大小,可以扩充到100M的大小

init_task->signal->rlim

[RLIMIT_STACK]      = {       _STK_LIM,  RLIM_INFINITY },

_STK_LIM即为当前系统中,进程用户栈的虚拟地址空间上限

#define _STK_LIM    (8*1024*1024)


异常分类

异常有7个

5+1(rst)+1(swi)

5:

vector_stub 中使用临时栈,然后切换到 swi mode , 使用 swi的栈

1(rst):

直接swi err0

1(swi):

直接使用 swi 的栈


arch/arm/kernel/setup.c


 136 /*                                                                               

 137  * Cached cpu_architecture() result for use by assembler code.                   

 138  * C code should use the cpu_architecture() function instead of accessing this   

 139  * variable directly.                                                            

 140  */                                                                              

 141 int __cpu_architecture __read_mostly = CPU_ARCH_UNKNOWN;                         

 142                                                                                  

 143 struct stack {                                                                   

 144     u32 irq[3];                                                                  

 145     u32 abt[3];       //对应 dabt 和 pabt 异常                                                           

 146     u32 und[3];                                                                  

 147     u32 fiq[3];                                                                  

 148 } ____cacheline_aligned;     // 对应5个异常及其对应的 vector_stub , vector_stub  中 这12个字节 用于 临时 stack .                                              

 149                                                                                  

 150 #ifndef CONFIG_CPU_V7M                                                           

 151 static struct stack stacks[NR_CPUS];                                             

 152 #endif



start_kernel

setup_arch

setup_processor

cpu_init

setup stacks for re-entrant exception handlers

struct stack *stk = &stacks[cpu];

556     __asm__ (                                                                    

557     'msr    cpsr_c, %1nt'                                                      

558     'add    r14, %0, %2nt'                                                     

559     'mov    sp, r14nt'                                                         

560     'msr    cpsr_c, %3nt'                                                      

561     'add    r14, %0, %4nt'                                                     

562     'mov    sp, r14nt'                                                         

563     'msr    cpsr_c, %5nt'                                                      

564     'add    r14, %0, %6nt'                                                     

565     'mov    sp, r14nt'                                                         

566     'msr    cpsr_c, %7nt'                                                      

567     'add    r14, %0, %8nt'                                                     

568     'mov    sp, r14nt'                                                         

569     'msr    cpsr_c, %9'                                                          

570         :                                                                        

571         : 'r' (stk),                                                             

572           PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),                                

573           'I' (offsetof(struct stack, irq[0])),                                  

574           PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),                                

575           'I' (offsetof(struct stack, abt[0])),                                  

576           PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),                                

577           'I' (offsetof(struct stack, und[0])),                                  

578           PLC (PSR_F_BIT | PSR_I_BIT | FIQ_MODE),                                

579           'I' (offsetof(struct stack, fiq[0])),                                  

580           PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)                                 

581         : 'r14');


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • PIC单片机控制的遥控防盗报警器电路

  • 短波AM发射器电路设计图

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 如何构建一个触摸传感器电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章