本文是在准备秋招时,对内存有了一个比较清晰的认识之后,开始写的。

目前先写这篇,后续会全部完善计算机系统的知识。

参考链接:

此处内存模型的概念,适用于三个地方的理解:

1.这个内存模型是一个进程的内存分配图;

2.这个内存模型是虚拟内存分配给一个进程的内存分配图;

3.这个内存模可以是一个C/C++程序的内存分配;

一、存储器层次结构

内存架构 内存架构模型_c++

这是一个计算机系统的所有内存层次结构图,从CPU的寄存器到硬盘,L0速度最快,L6速度最慢

  • 一个CPU的核心访问L1 cache
  • 同一个CPU的多个核心访问L2 cache
  • 所有CPU能访问L3 cache以及内存
  • L1 cache、L2 cache、L3 cache的容量空间依次变大,但是访问速度依次变慢

内存架构 内存架构模型_c++_02

然后内存模型的分区是存在与L4层次的DRAM,计算机内存中。

二、内存模型

下图以32位操作系统为例,1GB为操作系统的内核空间,用户无法更改,这部分不用管它;剩下的3GB位用户的内存空间,这是供用户程序使用的。

从上至下,依次为:

栈区(Stack):

由编译器自动分配释放 ,存放函数的参数值,局部变量的值等,内存的分配是连续的;

使用栈空间存储函数的返回地址、参数、局部变量、返回值,从高地址向低地址增长。在创建进程

时会有一个最大栈大小。如果定义的变量或者函数超出了这个最大栈大小,就会发生栈溢出现象

共享库的内存映射区(Memory Mapping Segment):

这个区也可以称做共享内存,主要有两个功能:

一是在程序链接阶段,会进行库链接,而链接的库则会保存在这里。链接又分为静态链接和动态链接,这里属于另外一个知识点,暂时不展开,后续单独开一个文章来写。只需知道这里保存者许多库文件即可。

二是给进程间通信提供一种方式,那就是共享内存,此时通过内存映射来实现。这里也是属于进程一块的知识,暂时不展开。

基于此,这块的功能大概就是上述两个。

堆区(Heap):

这块内存,就是由用户或者说程序员来主动开辟并释放的。

C语言中通过调用malloc/free,C++通过new/delete;这两个有点区别,一个属于函数,在stdlib.h库中,一个属于运算符;同时new还要调用构造函数,delete调用析构函数。

.bss 段:

这部分内存存储的是:

未初始化的 全局变量 和 静态变量(局部+全局

所有被初始化为 0 的 全局变量 和 静态变量

.data 段:

这部分内存存储的是:

已初始化的 全局变量 和 静态变量

总结:其实 .bss 和 .data段应该合称为数据段,它包括了未初始化的变量,已初始化的变量,文字常量rodata。C++语言将这些合称为数据段。如果从汇编角度去细分,就可以分成三个部分。

区别初始化和非初始化是为了空间效率。未初始化变量不占据实际内存空间(bss变量只在段表中记录大小,在符号表中记录符号。当文件加载运行时,才分配空间以及初始化),BBS段在程序执行之前会被系统自动清0,所以未初始化的全局变量和静态变量在程序执行之前已经为0。(也正是因为反正在bss上的变量肯定都是0,所以不需要为他们分配空间)

.text 段

这部分存储的是:

只读存储区;文本区;

只读存储区存储字符串常量;

文本区存储程序的机器代码

内存架构 内存架构模型_内存架构_03

到此为止,基本已经介绍完了程序的内存分配模型。特别注意,这里上述的每个区,我都称之为段,这个“段”就是内存管理中的分段机制所指的段,分段的大小是由用户空间决定的,因此每个段的大小是不相同的。

但是如果要更深入的理解这些概念,那么你还必须理解操作系统的其他概念,包括进程通信,内存管理知识以及最重要的,一个程序从编写到运行整个过程中经历了哪些阶段,这些都和上述整个模型息息相关。