内存分段 🆚 内存分页

参考博客

内存碎片🧩

内部内存碎片

外部内存碎片

解决的办法就是内存交换:即把某个程序占用的内存先写到硬盘中,接着释放其占用的内存空间;之后再把信息读回到内存中。不过再读回时占用的内存和之前占用的内存不一样,而是紧邻之前分配过的内存,以期减少外部内存碎片。
内存交换空间,从硬盘划分出来,用于内存与硬盘的交换,对应Linux中的Swap分区

内存分段

按需分配内存,因此不会有内部碎片;但是每个程序需要使用的每个段大小不一样,所以多个段未必能恰好使用所有的内存空间;因此会产生很多不连续的小内存,产生外部碎片问题。

此外,内存分段使得发生内存交换时,需要交换一块很大的区域,因此导致内存交换的效率很低

内存分页

分段的好处是能产生连续的物理内存空间,但是会出现「外部内存碎片和内存交换时数据太大」的问题。
「分页」:把物理内存和虚拟内存切成一块块固定大小的尺寸,页

内存分页机制分配内存的最小单位是页,因此不会出现外部内存碎片。但是即使程序使用内存不足一页,也要为其分配一个页的内存,因此内部会有部分空间浪费,因此内存分页机制会出现内部碎片

如果内存不够,OS会把其它进程中「最近未被使用」的内存页上的信息写到磁盘中,并释放对应的内存空间,这叫做换出;当这部分信息需要的时候,再把它加载到内存中,这被称为换入。所以一次性换入/出的也只有少数的几个页,因此内存交换的效率较高。

进一步的,程序可以使用延迟加载的机制;在需要的时候再把数据加载到物理内存中。

使用多级页表进一步降低存储页表需要的内存空间。对于二级页表来说,占用4KB的1024个一级页表项就可以覆盖4G的物理内存空间;且一个程序使用到的物理内存远小于4G,因此有很多的二级不需要建立 => 空间局部性原理

段页式内存管理

X86的内存分页机制

分页运行在分段基础上:先由分段管理机制将程序的「逻辑地址」转换为「线性地址」(虚拟地址),再由页式管理单元将「线性地址」转换为「物理地址」。

为了屏蔽x86的这一硬件要求,运行在x86上的Linux中的每个段都是从0开始的整个4GB地址空间,因此OS代码、应用程序代码看到的都是线性地址

程序虚拟内存布局

每个程序都有自己的页表

用户空间布局

用户空间最上方:栈 -> 「待分配区域」| 文件映射区 | 「待分配区域」<- 堆 <->「 BSS」、「数据段」、「代码段」、「保留区」。

  • malloc : 从堆区分配内存
  • mmap : 从文件映射区分配内存
  • 文件映射区:还会存放动态库中的代码段、数据段、BSS段

内存分段 🆚 内存分页
http://example.com/2024/09/07/嵌入式-开发/内存分段 🆚 内存分页/
作者
Cyokeo
发布于
2024年9月7日
许可协议