Linux内存管理的分页机制

分段机制的原理如下:

分段机制下的虚拟地址由两部分组成,段选择子段内偏移量。段选择子就保存在段寄存器里面。段选择子里面最重要的是段号,用作段表的索引。段表里面保存的是这个段的基地址、段的界限和特权等级等。虚拟地址中的段内偏移量应该位于 0 和段界限之间。如果段内偏移量是合法的,就将段基地址加上段内偏移量得到物理内存地址。

将上面的虚拟空间分成以下 4 个段,用 0~3 来编号。每个段在段表中有一个项,在物理空间中,段的排列如下图的右边所示。

如果要访问段 2 中偏移量 600 的虚拟地址,我们可以计算出物理地址为,段 2 基地址 2000 + 偏移量 600 = 2600。

在 Linux 里面,段表全称段描述符表(segment descriptors),放在全局描述符表 GDT(Global Descriptor Table)里面,会有下面的宏来初始化段描述符表里面的表项。

复制代码
#define GDT_ENTRY_INIT(flags, base, limit) { { { \
    .a = ((limit) & 0xffff) | (((base) & 0xffff) << 16), \
    .b = (((base) & 0xff0000) >> 16) | (((flags) & 0xf0ff) << 8) | \
      ((limit) & 0xf0000) | ((base) & 0xff000000), \
  } } }

一个段表项由段基地址 base、段界限 limit,还有一些标识符组成。

其实 Linux 倾向于另外一种从虚拟地址到物理地址的转换方式,称为分页(Paging)。

对于物理内存,操作系统把它分成一块一块大小相同的页,这样更方便管理,例如有的内存页面长时间不用了,可以暂时写到硬盘上,称为换出。一旦需要的时候,再加载进来,叫做换入。这样可以扩大可用物理内存的大小,提高物理内存的利用率。

这个换入和换出都是以页为单位的。页面的大小一般为 4KB。为了能够定位和访问每个页,需要有个页表,保存每个页的起始地址,再加上在页内的偏移量,组成线性地址,就能对于内存中的每个位置进行访问了。

虚拟地址分为两部分,页号页内偏移。页号作为页表的索引,页表包含物理页每页所在物理内存的基地址。这个基地址与页内偏移的组合就形成了物理内存地址。

当然对于 64 位的系统,两级肯定不够了,就变成了四级目录,分别是全局页目录项 PGD(Page Global Directory)、上层页目录项 PUD(Page Upper Directory)、中间页目录项 PMD(Page Middle Directory)和页表项 PTE(Page Table Entry)。

此文章为11月Day1学习笔记,内容来源于极客时间《趣谈Linux操作系统》,推荐该课程。

相关推荐
蒲公英源码3 分钟前
基于Linux+Nginx+PHP+MySQL的命理测算系统
linux·nginx·php
豆浆whisky4 分钟前
构建可观测的Go应用:指标、日志与追踪的统一之道|Go语言进阶(21)
linux·运维·后端·golang
java_logo8 小时前
MySQL Server Docker 容器化部署指南
linux·运维·数据库·docker·容器
誰能久伴不乏8 小时前
Linux文件套接字AF_UNIX
linux·服务器·c语言·c++·unix
a41324479 小时前
如何解决centos上oracle连接问题
linux·oracle·centos
h***34639 小时前
在linux(Centos)中Mysql的端口修改保姆级教程
linux·mysql·centos
星释9 小时前
Rust 练习册 97:Run-Length Encoding 压缩算法
java·linux·rust
2509_940880229 小时前
Linux(CentOS)安装 MySQL
linux·mysql·centos
可爱又迷人的反派角色“yang”9 小时前
LVS+Keepalived群集
linux·运维·服务器·前端·nginx·lvs