写堆栈,一是由于在工做中有时会碰到,脑子里有这个概念可是又没有一个完整的框架;二是我刚开始工做时,导师问我malloc,我竟彻底不知这个函数,更不知道malloc是从堆中分配内存,因此如今补上。算法
文中不少语句都是引用他人,无心抄袭,在此说明一下,如有冒犯,请告知。框架
这篇文章先从程序内存布局讲起,说明堆栈在Linux进程内存空间中的位置,而后再分别说明堆栈的基本概念、做用。函数
Linux进程内存布局布局
现代的应用程序都是运行在内存空间中的,在32位的系统里,这个内存空间拥有4GB的寻址能力。实际上,每一个应用程序(或者说进程)都有本身独立的内存空间,即经过虚拟内存来实现(具体虚拟内存知识暂不介绍)。性能
大多数操做系统都会将4GB的内存空间中的一部分分配给内核使用,应用程序没法访问这一段内存,这一部份内存空间称之为内核空间。Linux默认将高地址的1GB内存空间分配给内核。剩下的3GB内存空间称之为用户空间。在用户空间里,也有许多默认的内存区域,例如堆栈,可执行文件映像,保留区。下图是一个Linux典型的内存布局:操作系统
栈设计
1、什么是栈blog
栈是现代计算机程序里最重要的概念之一,几乎每个程序都使用了栈,没有栈就没有函数,没有局部变量。进程
在经典的计算机科学中,栈被定义为特殊的容器,用户能够将数据压入栈中(入栈,push),也能够将已经压入栈中的数据弹出(出栈,pop),且栈遵照一条规则,即先入后出。内存
经典的操做系统中,栈老是向下生长。在i386下,栈顶由称为esp的寄存器进行定位,压栈的操做会使栈顶的地址减少,弹出的操做使栈顶的地址增大。
2、栈的做用是什么
栈在程序运行中具备举足轻重的地位,最重要的,栈保存了一个函数调用所须要的维护信息,一般被称为堆栈帧(stack frame)或活动记录。堆栈帧通常包括如下几方面的内容:
--函数的返回地址和参数
--临时变量:包括函数的非静态局部变量以及编译器自动生成的其余临时变量
--保存的上下文:包括在函数调用先后须要保持不变的寄存器
堆
1、堆的定义和做用
光有栈对于面向过程的程序设计还远远不够,由于栈上的数据在函数返回的时候就会被释放掉,因此没法将数据传递至函数外部。而全局变量没法动态产生,只能在编译的时候定义,不少状况下缺少表现力。在这种状况下,堆(heap)是惟一的选择。
堆是一块巨大的内存空间,经常占据整个虚拟空间的绝大部分。在这片空间里,程序能够请求一块连续内存,并自由的使用,这块内存在程序主动放弃以前会一直保持有效。
malloc是libc里面实现的一个函数,中文叫动态内存分配,用于从堆中获取内存。可是malloc是如何实现的呢?有一种实现方法是,将进程的内存管理交给操做系统去处理,既然内核管理着进程的地址空间,那么若是它提供一个系统调用,可让程序使用这个系统调用来申请内存,这是一种理论上可行的方法,可是实际这样去作性能会很是差,由于每次程序申请或者释放堆空间都须要进行系统调用,而系统调用的性能开销很是大,当程序对堆的操做越频繁时,这样作的后果是会严重影响程序的性能。比较好的作法是程序向操做系统申请一块适当大小的空间,而后由程序本身管理,而具体来说,管理着堆空间分配的每每是程序的运行库。
运行库至关因而向操做系统“批发”了一块较大的堆空间,而后“零售”给程序用。当所有“售完”或者有大量的内存需求时,再根据实际需求向操做系统“进货”。运行库在向程序零售堆空间时,必须管理他批发来的堆空间,不能把同一块地址出售两次,因而运行库须要一个算法来管理堆空间,即堆的分配算法。