物理地址、线性地址、虚拟地址和逻辑地址以及页表

news/2024/7/20 13:30:34 标签: 虚拟地址, 页表, MMU, TLB, 内存管理

物理地址

用于芯片级内存单元寻址,对应着与CPU相连的地址总线。地址总线宽度决定了系统寻址能力,比如32位总线地址的寻址为2^32,即4G。但对于64位总线地址,那就是2^64,在目之所及的将来也是足够的。以系统启动时打印的E820表为例,该系统物理地址范围是0x0000000000000000-0x000000023fffffff,对应的物理内存大概是8G的空间,中间还有一些IO口和PCI设备占据一定空间,具体可以查看/proc/iomem。

BIOS-provided physical RAM map:
BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable   ---630K
BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved ---1K
BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved ---63K
BIOS-e820: [mem 0x0000000000100000-0x00000000bffd9fff] usable   ---3070M
BIOS-e820: [mem 0x00000000bffda000-0x00000000bfffffff] reserved ---151K
BIOS-e820: [mem 0x00000000feffc000-0x00000000feffffff] reserved ---15K
BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved ---255K
BIOS-e820: [mem 0x0000000100000000-0x000000023fffffff] usable   ---5119M

但是实际程序并不是使用物理地址来访问,如果使用物理地址,每个进程都可以操作同一个地址,那就无法保证多个进程的隔离性;同时也十分容易把内核搞崩。

线性地址(即虚拟地址)

线性地址,即虚拟地址,对应的是虚拟内存。在虚拟内存下,每个进程都有相同的虚拟地址空间,但是实际对应的物理页面是不同的。有了虚拟内存这一层封装,程序就不需要关注具体物理内存位置,专注自己的逻辑即可,因而程序运行时都是通过虚拟地址来访问指令和数据。

比如符号表/boot/System.map中记录的就是内核函数的虚拟地址,我们调用函数时,最终就是到对应的内存地址上获取指令。

ffffffff81a7b700 d traceon_count_probe_ops
ffffffff81a7b720 d func_opts
ffffffff81a7b740 d func_flags
ffffffff81a7b760 d tracer_flags
ffffffff81a7b780 d trace_opts
ffffffff81a7b7a0 d wakeup_prio

逻辑地址

包含在机器语言指令中,用来指定操作数或者操作指令的地址,每个逻辑地址由一个段和偏移量组成。引入逻辑地址是为了兼容远古时代的段式内存管理方式。那时还是直接使用物理地址,为了支持多进程并发,需要对各个进程重定位。目前的系统已经不需要通过这种方式。

物理内存的管理

面对几G甚至几T的内存,为了便于管理,我们把物理内存按照某个大小(一般是4K)来分割,分而治之,形成一个个页帧。而虚拟内存层面,则用页来表示。那这中间的映射关系维护,就需要页表来完成。

页表

用来将虚拟地址空间映射到物理地址空间的数据结构称为页表。但对虚拟地址空间中的每一页,都分配一个数组项也会有问题,我们以32位系统为例,虚拟地址空间为2^32,即4G,按每页4K大小,需要4*1024*1024/4,约100万,更不用说大得多的64位虚拟地址空间。

由于虚拟地址空间的大部分区域都没有使用,也就不需要关联到页帧,那么就可以使用功能相同,但内存用量少得多的模型:多级分页。

目前,64位Linux系统采用四级分页,

  • 页全局目录(Page Global Directory)
  • 页上级目录(Page Upper Directroy)
  • 页中间目录(Page Middle Directory)
  • 页表(Page Table)

在这里插入图片描述但并不是64位都用来寻址,我们只使用其中的48位,寻址空间为2^48,即256TB。在x86_64平台下,线性地址分级为9+9+9+9+12,对应的bit shift如下:

#define PGDIR_SHIFT		39
#define PUD_SHIFT		30
#define PMD_SHIFT		21
#define PAGE_SHIFT		12

对于进程,每一个进程有它自己的页全局目录和自己的页表集,当发生进程切换时,系统把cr3控制寄存器的内容保存在前一个执行进程的描述符中,然后把下一个要执行的进程的描述符的值装入cr3寄存器中。因此,当新进程重新开始在CPU上执行时,分页单元指向一组正确的页面。

MMUTLB_55">MMUTLB

通过多级页表我们可以节省大量内存,但是每次访问内存时,必须逐级访问多个数组才能将虚拟地址转换为物理地址。 针对这个问题,CPU引入两种方法来加速该过程,

  • MMU(Memory Management Unit),专门处理地址转换的单元,该单元优化了内存访问操作
  • TLB(Translation Lookaside Buffer),地址转换中出现最频繁的地址,会被保存到CPU高速缓存中,也就是TLB——地址转换后备缓冲器。这样就无需访问内存中的页表即可从高速缓存直接获得地址,从而加速地址转换

http://www.niftyadmin.cn/n/1035267.html

相关文章

SLUB缓存管理

注:本文分析基于linux-4.18.0-193.14.2.el8_2内核版本,即CentOS 8.2 1、关于SLUB 目前大多数系统都不使用slab作为缓存的管理模式,转而使用slub,比如CentOS 7和8默认都是使用slub管理器。slub是基于slab的进一步优化改进&#x…

安装和配置awscli

注:本文基于CentOS 7.4编写 1、安装awscli curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip ./aws/install安装完成后,我们查看下awscli的版本号, [rootloca…

CentOS 7安装python3

1、下载源码包 wget https://www.python.org/ftp/python/3.4.10/Python-3.4.10.tar.xz以Python-3.4.10为例,其他版本可以到https://www.python.org/ftp/python/,自行下载。 2、安装依赖、解压及编译安装 yum install -y zlib-devel bzip2-devel sqlit…

sap 计划订单(planned order)删除组件

转载自:https://blog.csdn.net/champaignwolf/article/details/80414269 最近碰到一需求,利用bapi(BAPI_PLANNEDORDER_CREATE)创建计划订单(planned order)在创建复制BOM时要根据自定义表内的组件信息去删除或修改要复制的BOM组件…

aws-shell的安装

1、aws-shell 使用awscli时会发现命令众多,一不小心就打错命令,这时我们可以考虑使用aws-shell这个小工具,它可以根据用户输入提示和补全命令。 2、安装aws-shell 我试过用python2.7安装aws-shell,会出现以下报错, …

CentOS 8重启网络服务

注:本文基于CentOS 8.4编写 CentOS 7中支持network.service和NetworkManager.service 2种方式配置网络,而在CentOS 8中已经废弃network.service,需要通过NetworkManager.service配置网络。因此通过systemctl restart network已经无法使用了。…

部署k8s dashboard

1 前提 已通过kubeadm搭建集群环境,具体可参考——使用kubeadm部署k8s 1.15集群——基于CentOS 7 2 创建dashboard应用 直接使用官网提供的yaml文件, kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.2.0/aio/deploy/r…

Kibana常用搜索语法

注:本文基于Kibana 7.13.4版本 1. Kibana搜索语法 Kibana的搜索语法分为两种类型, KQL,它是默认语法格式Lucene,它是可选格式 2. 常用搜索语法 2.1 精确匹配 比如匹配hostname为localhost,需要带双引号&#xff…