内存中的栈与堆

   在工作中遇到了内存栈和堆的一些问题,随手记录了下,比较零碎没有整理,也没有从概念开始介绍,只是把自己遇到的问题做了一些梳理,希望能对有需要的人帮助。

经典老图( 实际物理内存和进程虚拟内存都和上图结构一样,利用MMU进行地址转换 )


    1.   32位操作系统最大寻址空间为4GB, 即内存为4GB,最高字节1GB留给操作系统内核,称为内核空间。而将较低的3G字节(0x00000000-0xBFFFFFFF)供各个进程使用,称为 用户空间。每个进程都拥有一套属于它自己的页表,因此对于每个进程而言都好像独享了整个虚拟地址空间。每个进程可以通过系统调用陷入内核态,因此内核空间是由所有进程共享的。虽然说内核和用户态进程占用了这么大地址空间,但是并不意味它们使用了这么多物理内存,仅表示它可以支配这么大的地址空间。它们是根据需要,将物理内存映射到虚拟地址空间中使用。

    2.    栈由高地址向低地址生长,需要“先进后出”,由操作系统自己申请自己释放。堆由低地址向高地址生长。内存中的堆与操作系统中的堆不一样,无需先入先出,因为是零散的内存空间碎片,所以弹出顺序任意,一般由链表维持空余空间,有多种寻址算法。由用户手动申请手动释放。

    3.    内存中一个地址就代表 一个字节 。栈中为进程分配了默认的栈空间(最大值),实际使用空间是在编译和链接过程动态算出来的,不是每个都用了最大值。即,每个进程的栈空间大小都由他们自身决定。

    4.    理论上单个进程单独享用内存,切换进程时进行将之前进程上下文保存到flash, 后为提升效率,采用MMU虚拟内存+共享内存方式。实际物理内存中,保存多个进程上下文,好处是减少了切换到flash的开销,坏处是会造成内存踩踏。


多进程在内存中位置

    5.    每个线程所用的资源都在所属的进程内,在进程内每个线程拥有独立的栈和堆。

    6.    线程(非主线程)的栈的大小是固定的,其会在空闲的堆(堆顶附近自顶向下分配)或者是空闲栈(栈底附近自底向上分配),因此线程栈局部函数中分配的变量是存放到各自分配的栈空间,因此可以说是线程私有的,又因为该线程栈的边界是设定好的,因此该线程栈的大小的固定的,也就是ulimit -a 显示的值。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容