内存管理


1 基础

1.1 地址分类

  • 在linux中地址可分为3类,分别为:
  • 虚拟地址(Virtual Address):即我们在应用程序中所使用的地址,例如使用%p所打印出的地址就是虚拟地址
  • 线性地址(Linear Address):虚拟地址经过分段处理就变成了线性地址
  • 物理地址(Physical Address):线性地址经过内存管理单元(MMU)转换后就会成为物理地址,此转换过程称为分页
  • 线性地址空间的页是逻辑上的页,称为页表(Page Table),是虚拟的;物理空间的页,称为页框(Page Frame),是真实存在的,只是在逻辑上被划分为一页一页地,页大小一般为4K(也可能为2M、4M或1G)。后续说的分页就是将页表与页框联系起来的一个过程,具体分页有两个动作,其一是从页表上的地址找到页框上的地址(即寻址),其二是建立页表与页框之间的映射关系

1.2 分段与分页

  • Linux主要的4个段分别为:用户代码段(__USER_CS)、用户数据段(__USER_DS)、内核代码段(__KERNEL_CS和内核数据段(__KERNEL_DS),由于各段的段描述符的基准地址全为0,故转换后的线性地址与虚拟地址相等
  • 分页从字面理解就是将内存逻辑上分为一页一页的,当CPU要访问某个地址(物理地址)的时候,必须先找到包含该地址的页,而这个页的地址又存在上一级页的项中;上一级页的地址又存在上上一级页的项中。以此类推,最高一级的页地址存在CPU的寄存器中
  • 故最终地址的索引流程为:寄存器->一级页->...->最终页->物理地址。这类似于身份证前6位的定位一样,前两位表示省份,34位表示市,56位表示区县

2 寻址

2.1 一个例子

  • 假设有一个寻宝游戏,玩家在一开始知道一个藏宝图[0x10, 0x20, 0x30, 0x40]和一个地点(市民广场),于是玩家来到了市民广场并在0x10坐标找到了第二个地点(深圳湾);之后玩家来到深圳湾并在0x20坐标处找到了第3个地点(梧桐山)并在0x30坐标找到了第4个地点(大鹏湾),最后玩家在大鹏湾的0x40坐标处寻得宝藏
  • 该玩家整体寻宝过程为:市民广场(Base1)+0x10(offset)->深圳湾(Base2)深圳湾(Base2)+0x20(offset)->梧桐山(Base3)梧桐山(Base3)+0x30->大鹏湾(Base4)大鹏湾(Base4)+0x40->宝藏。对玩家而言,他只是拿到偏移量