虚拟内存,MMU/TLB,PAGE,Cache

本文探讨了虚拟内存的工作原理及其对程序独立性与内存管理的重要性,并深入剖析了缓存的几种不同设计方式及其对系统性能的影响。

原帖:http://hi.baidu.com/gilbertjuly/item/6690ba0dfdf57adfdde5b040


虚拟地址VA到物理地址PA以页page为单位。通常page的大小为4K。物理页面称为page frame。

查看应用程序进程的地址空间,可以看到分为很多段,比如代码段(只读)、数据段(读写)、堆、共享库(其中进一步分段)、栈空间等。整个应用程序的地址空间不会用满4GB,因为还有一部分是内核空间,应用程序不能访问。
再打开一个相同的应用程序查看其进程的地址空间,也是类似的,甚至是一样的。因为采用采用了虚拟地址,经过转换在物理地址上还是分开的。(代码段可能没有分开,因为可以共用)

采用虚拟内存的原因:
1.让每个进程有独立的地址空间,一个好处是某个进程不会破坏其他进程,另一个好处是每个进程都认为有4GB地址空间,编程方便。
2.物理上分开地址空间,经过虚拟内存的管理,可以使得逻辑上是连续的。
3.所有进程的虚拟内存之和可能大于物理内存。这是通过借用磁盘来实现的,将一时不用的虚拟内存保持到磁盘。磁盘上这部分成为交换设备,可以是分区,也可以是一个文件。所以系统中可分配的内存总量 = 物理内存的大小 + 交换设备的大小 。交换的过程成为页的换入和换出,期间需要对内存重新映射。
4.增加内存的保护属性,如内核地址空间、只读地址空间等。

虚拟地址到物理地址是一个查表的过程,但可能不只一个表,是一个多级的表。虚拟地址本身分为几个部分,page地址和page内地址(对于4KB的页来说就是11bit),page地址分为多级用于查表。这个过程称为Translation Table Walk,由硬件完成。上述所指的表,是保存在内存上的。

page大,page table小;
page大,减少TLB的miss;
page大,分配memory容易造成浪费;



上图给出了CPU,MMU,Cache的布局,MMU应该包括了TLB和Translation Table Walk。TLB(Translation Lookaside Buffer)是一块高速缓存,缓存最近查找过的VA对应的页表项。如果TLB中有需要查表的VA,就不用Translation Table Walk了,Translation Table Walk较慢要从内存上读页表。

Cache的储存单位是line,假设每个line有32bytes。为了表示某个line是属于哪个VA的,Cache里还有TAG。最简单的TAG就是VA的地址了(按32bytes的line对齐),Cache控制器检查CPU给出VA和TAG是否一致,一致的话表示命中(Hit),将数据返回给CPU,否则的话靠MMU转成PA从内存中读取数据。

上述这个Cache的设计称为全相联,特点是一个VA可以缓存到任何line里,但问题是Cache可能有很多line,比如512个line,每次都需要一个个TAG比较过来,这样速度较慢。
另一种Cache的设计称为直接映射,特定的VA只能存在特定的Cache line里,映射规则为Cache line = (VA line)%(Cacle line总数)。这样的问题是Cache line里的数据进出可能太过于平凡,导致命中率较低。

全相联Cache和直接映射Cache各有优缺点,全相联Cache查找很慢,但没有抖动问题(命中率低),直接映射Cache则正相反。实际CPU的Cache设计是取两者的折衷,把所有Cache Line分成若干个组,每一组有n条Cache Line,称为n路组相联Cache(n-way Set Associative Cache)。n路组相联Cache的特点是特定的内存行只能放在特定的组内,但是可以放在组内的任意cache line上。
        
Cache写回内存有两种模式:
Write Back:Cache Line中的数据被CPU核修改时并不立刻写回内存,Cache Line和内存中的数据会暂时不一致,在Cache Line中有一个Dirty位标记这一情况。当一条Cache Line要被其它VA的数据替换时,如果不是Dirty的就直接替换掉,如果是Dirty的就先写回内存再替换。

Write Through:每当CPU核修改Cache Line中的数据时就立刻写回内存,Cache Line和内存中的数据总是一致的。如果有多个CPU或设备同时访问内存,例如采用双口RAM,那么Cache中的数据和内存保持一致就非常重要了,这时相关的内存页面通常配置为Write Through模式。


    
    page是os的概念,而cache是cpu的概念。虚拟地址和物理地址以page为单位进行操作的,由两部分组成:page地址和page内地址:



 采用多路组联的cache,如之前所述,这样的Cache分为多个set(组),每个组里面又有多个line/way(行),每个line里面又有多个字节。



对某个page进行操作时,会将page分配到cache里,这种分配是按照一定关系的。
    
    假设page的大小为4KB,考虑物理地址;
    cache的大小为2M,16384个4-Way SET,32 Bytes line,即32*4*16384=2M。
    执行memset(0, 0, 4*1024)的话,这4KB内存在cache上会放在连续的0到127set中每个set的第1个line;
    执行memset(1, 0, 4*1024)的话,这4KB内存在cache上会放在连续的128到255set中每个set的第1个line;
    ...
    执行memset(128, 0, 4*1024)的话,这4KB内存在cache上会放在连续的0到127set中每个set的第2个line;
    执行memset(129, 0, 4*1024)的话,这4KB内存在cache上会放在连续的128到255set中每个set的第2个line;
    
    就是说第ith物理页面会与第(128*j+i)th个物理页面中Cache中占据同样的Cache Sets。Set满了之后,按照一定的算法 ,比如LRU算法(Least Recently Used algorithm)清除之前的数据。


以上说的是现象,产生上述现象的原因可以用下图来解释:



    物理地址的位5-11是page中的偏移地址,7位,可以表示128个set;
    物理地址的位12-31是page frame地址的,对某一个page来说是固定的,决定了上述128个set在cache中的位置。
    
    128个set的合集有个专用的名词,称为Cache Bin。



<think>好的,我现在需要解释用户提到的几个关于内存初始化的步骤:检测物理内存布局、建立内存控制器时序、建立内存映射表、初始化MMU/Cache机制。首先,我要回忆这些步骤在系统启动过程中的作用,尤其是嵌入式系统或MTK芯片启动流程中的位置。 用户之前的问题是关于F2FS/EXT4驱动加载和fsck的,现在转向内存管理,可能是在学习系统启动流程的不同阶段。我需要确保回答结构清晰,分步骤解释,同时注意术语的准确性。 首先,检测物理内存布局。这可能涉及系统如何识别可用的物理内存区域,包括不同内存段的地址范围(如DRAM、保留内存等)。需要说明为什么需要这一步,比如不同硬件平台内存大小和布局可能不同,系统必须正确识别才能有效管理。 接下来是建立内存控制器时序。内存控制器负责与物理内存(如DRAM)的通信,时序设置涉及时钟、延迟参数等,确保读写操作正确。这部分可能比较技术,需要解释时序参数的重要性,比如CAS延迟、tRCD等,以及错误配置的后果,如系统不稳定或崩溃。 然后是建立内存映射表。这应该是指虚拟地址到物理地址的映射,可能包括内存区域的属性(如可读、可写、可执行,缓存策略等)。需要说明内存映射表的作用,让CPU知道如何访问物理内存,以及不同区域(如设备内存、常规内存)的处理方式。 最后是初始化MMU/Cache机制。MMU(内存管理单元)负责虚拟地址转换,而Cache用于加速内存访问。这里需要解释MMU如何利用页表进行地址转换,Cache的工作机制,以及初始化这些组件对系统性能和安全性的影响。 我需要确保每个步骤的解释都包含定义、目的、实现方式以及常见问题或注意事项。同时,可能需要用例子或比喻来帮助理解,比如将内存映射表比作地图,MMU比作导航系统等。还要注意用户可能的技术背景,避免过于晦涩或过于简化。 另外,用户之前的问题提到了MTK芯片的启动流程,可能需要联系到具体的芯片架构,比如ARM的处理方式,或者MTK特有的实现。不过如果信息不足,保持通用性可能更安全。 需要检查是否有遗漏的步骤,或者是否需要深入某个点。例如,检测物理内存布局可能涉及ACPI或设备树(Device Tree)的信息读取,而建立内存控制器时序可能涉及配置寄存器设置。这些细节是否需要展开?用户要求详细解释,所以可能需要适当的技术深度,但避免冗长。 最后,结构上可以按照用户列举的顺序,分四个部分,每个部分一个小标题,类似之前的回答结构。使用术语定义、执行逻辑、技术细节、典型场景等方式可能有助于清晰呈现。同时,保持中文口语化,避免过于生硬的学术表达。</think>--- ### 一、整体背景 在系统启动(尤其是嵌入式/SoC设备如MTK芯片)的早期阶段,内存管理初始化是核心任务之一。这些操作确保CPU能正确识别、访问物理内存,并为后续操作系统运行提供稳定环境。以下是逐项解析: --- ### 二、术语定义与详细解释 #### 1. **检测物理内存布局** - **定义**: 扫描硬件信息,确定可用物理内存的地址范围、容量及类型(如DRAM、ROM、保留区域)。 - **技术实现**: - 通过读取芯片手册或设备树(Device Tree)获取内存信息 - 调用`detect_memory()`函数遍历内存段(示例代码): ```c for (mem_block in memory_map) { if (mem_block->type == RAM) add_to_available_mem_list(mem_block); } ``` - **典型问题**: - 内存重叠或空洞(如硬件保留区域未正确标记) - 错误识别内存类型(如误将MMIO区域视为DRAM) --- #### 2. **建立内存控制器时序** - **定义**: 配置内存控制器(如DRAM Controller)的时序参数,确保对物理内存的读写操作符合硬件规范。 - **关键时序参数**: - **tCL** (CAS Latency):列地址选通延迟 - **tRCD** (RAS to CAS Delay):行到列选通延迟 - **tRP** (Row Precharge Time):行预充电时间 - **操作流程**: 1. 根据内存芯片规格书(如LPDDR4数据手册)设置寄存器 2. 写入时序参数至内存控制器的配置寄存器(示例伪代码): ```c dram_ctrl->tCL = 14; // 单位:时钟周期 dram_ctrl->tRCD = 16; ``` - **失败后果**: - 数据读写错误(表现为系统崩溃或内存校验失败) - 内存带宽下降(时序过保守)或稳定性风险(时序过激进) --- #### 3. **建立内存映射表** - **定义**: 定义虚拟地址到物理地址的映射关系,并设置内存区域的访问权限(如可读/写/执行)。 - **映射类型**: - **恒等映射**:虚拟地址=物理地址(用于启动初期) - **动态映射**:操作系统内核空间与用户空间的分隔 - **技术实现**(以ARM为例): - 构建页表(Page Table)描述符,写入`TTBR0`/`TTBR1`寄存器 - 示例页表项格式: ``` | 物理地址基址 | 权限位 | 缓存策略 | ... ``` - **典型场景**: - 将设备内存(如GPU显存)映射为不可缓存(Non-cacheable) - 内核代码区标记为只读(防止意外修改) --- #### 4. **初始化MMU/Cache机制** - **MMU(内存管理单元)**: - **功能**:将虚拟地址转换为物理地址,并实施访问权限控制 - **初始化步骤**: 1. 使能MMU前需先建立基础内存映射(如恒等映射) 2. 设置`SCTLR`寄存器开启MMU(ARM指令示例): ```asm mrc p15, 0, r0, c1, c0, 0 orr r0, r0, #1 << 0 // 开启MMU mcr p15, 0, r0, c1, c0, 0 ``` - **Cache机制**: - **作用**:缓存热点数据以减少内存访问延迟 - **初始化关键操作**: - 设置缓存策略(Write-back/Write-through) - 无效化(Invalidate)缓存以避免脏数据残留 ```asm mcr p15, 0, r0, c7, c14, 0 // 无效化Data Cache mcr p15, 0, r0, c7, c5, 0 // 无效化Instruction Cache ``` --- ### 三、关联性与执行顺序 ```text 启动流程 ├─ 1. 检测物理内存布局 → 明确硬件资源 ├─ 2. 配置内存控制器时序 → 确保DRAM稳定工作 ├─ 3. 建立内存映射表 → 定义地址转换规则 └─ 4. 初始化MMU/Cache → 启用虚拟内存与缓存加速 ``` --- ### 四、故障案例与调试 1. **内存检测失败**: - **现象**:系统启动卡在`Detecting RAM...` - **排查**:检查设备树中内存节点(如`memory@80000000`)是否正确 2. **时序配置错误**: - **现象**:内存压力测试(如memtester)报错 - **调试**:使用示波器测量DRAM时钟信号是否符合时序图 3. **MMU未生效**: - **现象**:访问虚拟地址触发`Data Abort`异常 - **验证**:通过`MMU Fault Address Register`读取错误地址 --- ### 五、性能优化方向 1. **动态调整Cache策略**:对DMA缓冲区禁用缓存以减少一致性开销 2. **大页表(Huge Page)**:减少TLB Miss以提升虚拟化性能 3. **内存预取**:根据访问模式预加载数据至Cache 通过上述步骤,系统能够高效、安全地管理内存,为后续加载内核及驱动奠定基础。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值