乐趣区

关于linux:笨叔点滴3-栈谁便宜了

“有一次和女同学 A 吃饭,她带着小姑凉一块。在吃饭期间,同学给夹了块豆腐,小姑凉用天真无邪的眼神看着我:笨叔,你除了占我妈便宜,你还占过谁的便宜?我登时无语了。。。”

下面是网上的一个小段子,生存里常常有人说谁谁占了谁的便宜?那计算机是不是也有占小便宜呢?计算机里还真有不少便宜能够“栈”,只不过不是“占”,而是各种模式的“栈”,不晓得大家知不知道计算机里有多少个栈?比如说:

 内核栈

中断栈

过程栈

线程栈

硬件栈

软件栈

堆栈

还有人占着茅坑



    昨天咱们聊了 ARM32 上或是奇葩或者先进的中断栈,咱们明天持续来聊“栈”。

01 啥是栈

先看看啥是栈?栈的英文叫做 stack。那中文里栈是怎么解释的呢?

1. 贮存货物或供旅客住宿的屋宇:货栈|客栈。

2. 养家畜的竹、木栅栏:马栈。

那在计算机,它是啥呢,其实就是一个存放数据的数据结构类型。一种只能在一端进行插入和删除操作的非凡线性表。它依照先进后出的准则存储数据,先进入的数据被压入栈底,最初的数据在栈顶,须要读数据的时候从栈顶开始弹出数据(最初一个数据被第一个读出来)。看上面这个图应该比较清楚了。

这种数据结构的特点是 后入先出 (LIFO, Last In First Out),数据只能在串列的一端 (称为:栈顶 top) 进行 推入 (push) 和 弹出 (pop) 操作。向栈中存储数据称为 PUSH,从栈中取数据称为 POP。

大多数的处理器架构,都有实现硬件栈。有专门的栈指针寄存器,以及特定的硬件指令来实现 入栈 / 出栈 的操作。例如在 ARM 架构上,R13 (SP) 指针是堆栈指针寄存器,而 PUSH 是用于压栈的汇编指令,POP 则是出栈的汇编指令。

咱们经常听人说,堆栈,那堆栈是个什么鬼?到底是堆呢还是栈呢?其实堆栈自身就是栈,只是换了个形象的名字,换了个马甲,有些人就昏了。

那堆是什么?在数据结构里,堆能够被看成是一棵树,如:堆排序。在操作系统里,堆是操作系统里治理内存的一种形式,个别由程序员调配开释,若程序员不开释,程序完结时可能由 OS 回收,调配形式倒是相似于链表。而栈,由操作系统主动调配开释,寄存函数的参数值,局部变量的值等。

所以,堆和栈还有堆栈,他们三个是不是容易搞混了。

02 栈有啥子用嘛?

栈次要是有两大作用,一个是函数调用,另外一个是过程调度。

先说说函数调用。咱们晓得函数调用须要留神哪些货色?大家想到的可能是

参数怎么传

函数返回值怎么传

那在不同的计算机体系结构里,有不同的做法,然而他们雷同的中央是肯定会用到栈。

ARM 和 ARM64 应用的是 ATPCS(ARM-Thumb Procedure Call Standard/ARM-Thumb 过程调用规范) 的函数调用约定。

对于 ARM 来说:

参数 1~ 参数 4 别离保留到 R0~R3 寄存器中,剩下的参数从右往左一次入栈,返回值寄存在 R0 中。

对于 ARM64 来说:

参数 1~ 参数 8 别离保留到 X0~X7 寄存器中,剩下的参数从右往左一次入栈,返回值寄存在 X0 中。

总之,会用到栈来保留函数调用的参数。另外还有一个货色须要保留,那就是局部变量。

以 ARM32 为例,一个函数 A 调用另外一个函数 B 的栈的布局图如下。fp 寄存器(r11)和 sp 寄存器两个指向的区域,称为一个栈帧(stack frame),函数调用常常是嵌套的,在同一时刻,栈中会有多个函数的信息。每个未实现运行的函数占用一个独立的间断区域,即栈帧。栈帧寄存着函数参数,局部变量及复原前一栈帧所须要的数据等。

如上图所示,假如以后运行在函数 B 外面,那么以后的 fp 和 sp 寄存器所批示的区域就是以后的栈,栈帧 B。当函数 B 返回到函数 A 时候,栈帧 B 里保留的 sp 和 fp 寄存器所结构的另一个栈,就是栈帧 A 了。

所以,栈是链接起来的‘桢’的一个列表,按递加地址秩序调配栈的每一块。寄存器 sp 总是指向在最以后桢中最低的应用的地址。ARM 上栈有点奇葩。

其余 CPU 体系结构中说的 SP 栈指针,都是指向栈顶的,然而 ARM 的栈是自减栈,栈是向下成长的,也就是栈底处于高地址处,栈顶处于低地址处。有点奇葩和绕口。

栈还有另外一个用处就是过程切换。每个过程都有本人的零碎栈空间,这个栈空间说的是内核栈,这个是在 fork 的时候就调配好的。所以,过程切换的时候,须要把后任的过程的上下文保留到后任过程的内核栈里。在每一个过程的生命周期中,必然会通过到零碎调用陷入内核。在执行零碎调用陷入内核之后,这些内核代码所应用的栈并不是原先过程用户空间中的栈,而是一个独自内核空间的栈,这个称作过程内核栈。过程跑在用户空间,须要一个栈,过程跑在内核空间也须要一个栈,所以这些栈的定义是不一样。

咱们下一次在来和大家聊聊哪些“栈”谁的便宜。

最初一个问题,CPU 上电时候第一条指令为什么要用汇编来实现?能不能让 CPU 第一条指令就执行 C 语言的代码?

能还是不能?为啥子嘛?

退出移动版