linux系统中分段与分页

📅 2026/7/21 3:42:20 👁️ 阅读次数 📝 编程学习
linux系统中分段与分页

分段和分页均为操作系统管理物理内存的方式,分段划分物理地址为不同的功能段,实操着逻辑地址转化为线性地址,而分页则是将线性地址映射到不同的物理地址

地址分类方式

  • 逻辑地址:Linux程序使用的地址表示类型,例如段选择符+段偏移的分段逻辑地址
  • 线性地址:对整个物理地址进行排序编号后,可用于硬件寻址的地址
  • 物理地址:硬件中内存或存储真实的存储地址

分段

整个系统作为一个运行中的程序,必定存在代码和数据被CPU调用,如果给这些代码和数据提供固定的存储区域并且给出指针,这就是代码段和数据段。

针对不同的功能划分出的存储区域就是分段的雏形,依赖于功能实现,分段也就提出了读写分离等额外功能。

分段机制的具体运作主要涉及到逻辑地址到线性地址的转换。程序真实存储的段信息其实是有 Index+地址偏移的段选择符形式,将段选择符转化为线性地址需要一系列段寄存器和描述符表的帮助。

段选择符的形式是index+T0+offset,index直接代表段选择符对应的段描述符在段表中的序号,T0表示当前段选择符对应的是全局段表还是进程的局部段表,offset表示相对于段起始位置的偏移。

段选择符中的index * 8 + 段表起始位置即为段描述符所在位置,再由段描述符号中的段位置+ base即可获取段的线性地址。而T0代表的全局段表和局部段表由系统的寄存器gdtr或ldtr获取。

分页

分页机制允许程序将数据划分为不同的页,与物理存储的页框一一对应,方便系统进行权限管理和数据传输,主导的是从线性地址到物理地址这一转化。系统默认的页框大小为4KB,即默认以4KB大小进行存储管理和数据传输。

在32位系统下指针可指向的\(2^{32}\)大小的逻辑地址,而一页4KB覆盖了\(2^{12}\)个地址(为什么逻辑地址的单位是字节),因此逻辑地址可以划分为\(2^{20}\)张页。假设每个指向页表的页表项为32bit,直接存储所有逻辑地址的页表占用内存为\(2^{20}*32bit = 4MB\),在多进程同时保存逻辑地址到物理地址映射下,该方案显然是无效的。

Linux系统中实际的分页场景是更灵活的3级分页机制,系统存储一个全局的页目录表,用于维护真实加载所需的页表,而页表中的页表项才是真正对应到物理页框的元素。

32位系统中的逻辑地址由32位指针给定,默认分页大小4KB直接占用了指针的低12位,直接存储高20位占用的内存容量过高,所以Linux给出了页目录表的解决方案。页目录表根据指针前10位作为分类依据,在满负荷下仅需要4Kb的存储容量,而下一级的页表则根据实际加载的内存来灵活分配存储。

实际上也存在2级页表机制,通过扩大页表的存储载体,例如由用4KB页存储页表项扩大为使用2MB页存储页表项,直接使用页目录表来完成内存管理。

分页过程中也有着寄存器的参与,例如从CR3中获取到全局的页目录表,在发现页未进入内存中将地址存入CR2并引发缺页中断。