栈的作用

ARM 处理器程序运行的过程

ARM 芯片属于精简指令集计算机(RISC: Reduced Instruction Set Computing),它所用的指令比较简单,有如下特点:

  1. 对内存只有读、写指令
  2. 对于数据的运算是在 CPU 内部实现
  3. 使用 RISC 指令的 CPU 复杂度小一点,易于设计

比如对于 a=a+b 这样的算式,需要经过下面 4 个步骤才可以实现:
在这里插入图片描述
cpu 内部结构:cotex-a7 处理器模式 以及通用寄存器组

CPU 运行时,先去取得指令,再执行指令:
① 把内存 a 的值读入 CPU 寄存器 R0
② 把内存 b 的值读入 CPU 寄存器 R1
③ 把 R0、 R1 累加,存入 R0
④ 把 R0 的值写入内存 a

以上步骤完成了a+b的计算。

程序被中断时,怎么保存现场

当执行到一半时(比如刚把a、b读到R0、R1),中断发生了(或是调用函数、线程调度等等情况),cpu需要立即执行别的程序(别的程序也会用到 R0、R1啊,到时候数据就丢失了),所以在调度到新的执行单位时 必须将R0、R1保存起来(写到栈里,其实保存的不止R0、R1,还有指令寄存器PC 其它等等)。

栈说白了就是一段内存,用来给应用程序存储数据。

线程(中断)的调度方式

以下时线程调度时的示意图:
在线程 A 执行时,中断B发生,那么在跳转 B之前的瞬间需要把线程 A 的 CPU 寄存器的值,保存到栈里;再去执行线程 B;
线程B恢复线程A时也是同样的道理
在这里插入图片描述

在cpu执行程序中 函数调用、或是线程切换、发生中断等等情况下 ,都需要保护当前的现场,以保证能完整的还原。
保护现场: 将cpu 内部寄存器中的数据保存到栈中。
恢复现场: 将栈中的数据恢复到cpu 内部寄存器。

在操作系统中有以下几种情况会使用到栈:

a. 函数调用:
在函数 A 里调用函数 B,实际就是中断函数 A 的执行。
那么需要把函数 A 调用 B 之前瞬间的 CPU 寄存器的值,保存到栈里;
再去执行函数 B;
函数 B 返回之后,就从栈中恢复函数 A 对应的 CPU 寄存器值,继续执行。

b. 中断处理
进程 A 正在执行,这时候发生了中断。
CPU 强制跳到中断异常向量地址去执行,
这时就需要保存进程 A 被中断瞬间的 CPU 寄存器值,
可以保存在进程 A 的内核态栈,也可以保存在进程 A 的内核结构体中。
中断处理完毕,要继续运行进程 A 之前,恢复这些值。

c. 进程切换
在所谓的多任务操作系统中,我们以为多个程序是同时运行的。
如果我们能感知微秒、纳秒级的事件,可以发现操作系统时让这些程序依次执行一小段时间,进程 A 的时间用完了,就切换到进程 B。

怎么切换?
切换过程是发生在内核态里的,跟中断的处理类似。
进程 A 的被切换瞬间的 CPU 寄存器值保存在某个地方;
恢复进程 B 之前保存的 CPU 寄存器值,这样就可以运行进程 B 了。

所以,在中断处理的过程中,伴存着进程的保存现场、恢复现场。
进程的调度也是使用栈来保存、恢复现场:
在这里插入图片描述

总结

每个函数都有自己的栈,每个线程都有自己的栈。

在多线程任务模式,栈显得尤为重要。进程是cpu 分配资源的最小单位,线程是cpu 调度的最小单位,一个进程中可以有多个线程,它们虽然共用代码段、数据段(全局变量、静态变量等等)、堆等等,但是它们有属于自己的栈。这就保证了在调度的时候不会发生错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值