MMU解读
转:https://blog.csdn.net/yueqian_scut/article/details/24816757
mmu页表也是放在内存中,mmu里有一个寄存器存放页表首地址,从而找到页表(地址为物理地址)。当我们执行一个程序时,会把这个进程的mmu页表地址放到该寄存器中,跳转找到mmu页表执行。
TLB是MMU内部的缓存,页表是每个进程都有的一段保存虚拟地址到物理地址对应映射关系的数组,此数据在内存中
(TLB---Translation Lookaside Buffers,转译查找缓存):由于从MVA到PA的转换需要访问多次内存,大大降低了CPU的性能,故提出TLB办法改进。当CPU发出一个虚拟地址时,MMU首先访问TLB。如果TLB中含有能转换这个虚拟地址的描述符,则直接利用此描述符进行地址转换和权限检查,否则MMU访问页表找到描述符后再进行地址转换和权限检查,并将这个描述符填入TLB中,下次再使用这个虚拟地址时就直接使用TLB用的描述符。使用TLB需要保证TLB中的内容与页表一致,在启动MMU之前,页表中的内容发生变化后,尤其要注意。一般的做法是在启动MMU之前使整个TLB无效,改变页表时,使所涉及的虚拟地址对应的TLB中条目无效。
不同进程切换时,通过CR3(x86时)寄存器 把页表缓存地址传递给MMU模块,进而时MMU的TLB更新为对应进程的页表内容
程序的大部分代码都可以在必要的时候才加载到内存去执行,运行完后可以被直接丢弃或者被其他代码覆盖。我们PC上同时跑着很多的应用程序,每个应用程序使用的虚拟地址空间几乎可以整个线性地址空间(除了部分留给操作系统或者预留它用),可以认为每个应用程序都独占了整个虚拟地址空间(字长是32的CPU是4G的虚拟地址空间),但我们的物理内存只是1G或者2G。即多个应用程序在同时竞争使用这块物理内存,其必然会导致某个时刻只存在程序的某个片段在执行,也即是所有程序代码和数据分时复用物理内存空间—这就是内存管理单元(MMU)工作核心作用所在。
处理器系列的芯片(如X86、ARM7以上、MIPS)一般都会有MMU,跟操作系统一块实现虚拟内存管理,MMU也是Linux、Wince等操作系统的硬件要求。而控制器系统的芯片(面向低端控制领域,ARM1,2,MIPS M系列,80251等)一般都没有MMU,或者其只有单一的线性映射机制。
本文要谈的是控制器领域SoC的内存管理单元的硬件设计,其重要的理念同样是代码和数据分时复用物理内存空间,在保障系统功能和性能的基础上最大限度地节省物理内存的目的。相关的文章包括:SoC软件架构设计之一:系统内存需求评估和节省内存的软件设计技巧。
一、内存管理单元(MMU)的工作机制
在阐述控制器领域的内存管理之前,还是要先介绍处理器领域的虚拟内存管理机制,前者很大程度上是对后者核心机制精髓的借鉴。实现虚拟内存管理有几个模块是协调工作的:CPU、MMU、操作系统、物理内存,如图示(假设该芯片系列没有cache):
我们根据上图来分析一下CPU访问内存的过程,假设寻址是0x10000008,一页大小为4K(12比特)。则虚拟地址会分成两个部分:页映射部分(20bit,0x10000)+页内偏移(12bit, 0x8)。CPU通过总线把地址信号(0x10000008)送给MMU,MMU会把该地址的页映射部分(20bit)拿到TLB中匹配。
TLB是什么东西?Translation Lookaside Buffer,网上有称为“翻译后备缓冲器”。这个翻译都不知道它干什么。它的作用就是页表的缓冲,我喜欢叫它为页表cache。其结构图如下:
可以想象,TLB就是索引地址数组,数组的每个元素就是一个索引结构,包含虚拟页地址和物理页地址。其在芯片内部表现为寄存器形式,一般寄存器都是32位,实际上TLB中的页地址也是32位寄存器,只不过索引比较时是比较前20bit,后12bit其实也是有用的,例如可以设置某个bit是表示常驻的,即该索引是永远有效的,不能更换,这种场景一般是为适合一些性能要求特别高的编解码算法而设计的。非常驻内存的一般在某个时刻(如TLB填满时访问一个新的页地址)就会发生置换。
1) 假如0x10000008的前20bit在TLB中第M个索引中命中,这时就表示该虚拟页在物理内存中已经给它分配好对应的物理内存,页表中也已经做好记录。至于虚拟地址对应的代码页是否从外存储(flash,card,硬盘)的程序中加载到内存中还需要要另外的标记,怎么标记呢?就是利用上面所讲的TLB低12位的某一bit(我们称为K)来标识,1标识代码数据已经加载到内存,0表示还没加载到内存。假如是1,那就会用M中的物理地址作为高20bit,以页内偏移0x8作为低12bit,形成一个物理地址,送到内存去访问。此时该次访问就会完成。
2) 假如K是0,那意味着代码数据尚未加载到内存,这时MMU会向中断管理模块输出信号,触发一个中断进行内核态,由操作系统负责将对应的代码页加载到内存。并修改对应页表项的K比特和TLB对应项的K比特为1.
3) 假如0x10000008的前20bit在TLB所有索引中都没有命中,则MMU也会向中断管理模块输出一个信号触发中断进入内核态,由操作系统将0x10000008右移12位(即除以4K)到页表中去取得对应的物理页值,假如物理页值非0有效,说明代码已经加载到内存了,这时将页表项的值填入到某一个空闲的TLB项中;假如物理页值为0,说明尚未给这个虚拟页分配实际的物理内存空间,这时会给它分配实际的物理内存,并写好页表的对应项(这时K是0),最后将这索引项写入TLB的其中一条。
2)和3)其实都是在中断内核态中完成的,为什么不一块做了呢?主要是因为一次中断不应该做太多事情,以加大中断延时,影响系统性能。当然如果有芯片将两者做成一个中断也是可以理解的。我们再来看看页表的结构。页表当然也可以按TLB那样做成索引数组,但是这样有两个不好的地方:
1)页表是要映射所有的虚拟页面的,其维护在内存中也需要不小的空间。页大小是4K时,那映射全部就是4G/4K=1M条索引,每条索引4*2=8个字节,就是8M内存。
2)假如按TLB那种结构,那匹配索引的过程就是一个for循环匹配电路,效率很低,要知道我们做这个都是在中断态完成的。
所以一般的页表都是设计成一维数组,即以整个线性虚拟地址空间按页为单位依次作为数组的下标,即页表的第一个字(4字节)就映射虚拟地址空间的最低4K,第二个字映射虚拟地址最低的第二个4K,以此类推,页表的第N个字就映射虚拟地址空间的第N个4K空间,即(N-1)*4K~4KN的地址空间。这样页表的大小就是1M*4=4M字节,而且匹配索引的时候只是一个偏移计算,非常快。
承前启后,在引出第二部分之前先明确两个概念:
1. Bank表示代码分块的意思,类似于上面提到的页的概念。
2.不同代码分时复用内存:不同代码即意味着不同的虚拟地址对应的代码,(程序链接后的地址都是虚拟地址),内存即物理内存,即一定大小的不同虚拟地址的代码在不同的时刻都跑在同一块一定大小的物理内存空间上。每一块不同的代码块即是不同的代码Bank。
二、控制器领域SoC内存管理单元的硬件设计
这里专指没有内存管理单元的SoC设计,一般为了降低成本,在性能足够时,如果16位或者24位字长CPU能够解决问题,一般都不会去选32位字长的CPU,除非是计算性能考虑,或者32位CPU的license更便宜(一般很少见)。只要能够达到高效地进行内存管理,实现物理内存分时复用的目的,那都可以称为是成功或者有效的。在介绍真正的内存管理单元硬件设计之前,我们先简单介绍一种利用工具链来实现内存分时复用的机制,然后再结合MMU和这个工具链实现的分块处理方法去设计我们新的内存管理单元,包括其硬件工作机制和软件设计和关键机制。
由于以下内容涉及到在审专利,经过考虑,暂时将以下内容隐藏,适当时候再公开,抱歉!
×××××××
后记补充
在集成没有MMU的CPU时,SoC要实现内存管理,需要另外设计一个内存管理模块,实现MMU的核心功能,即代码分页(块)映射的功能,而且需要简化设计以达到最高的效率,同时代码分块需要直接地体现在链接脚本上。为了追求效率,编译链接后的可执行性文件还会被离线解析组织成一个更简化的执行文件,把不需要的段都删除,并将分块代码按逻辑顺序放好,以便于操作系统在必要时更快地加载。当然,操作系统的代码内存管理也需要配合内存管理硬件电路,并能够解析重新打包后的执行程序文件。因此内存管理的实现是需要架构师从软件和硬件上全面考虑,尽可能地在实现核心功能的基础上简化电路和设计,涉及的模块包括:硬件机制设计、物理内存分配、代码分块原则、linker脚本定义、打包执行文件、操作系统定制等等。后续阐述的架构设计将会包括以上内容。
---------------------
本文来自 吴跃前 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/yueqian_scut/article/details/24816757?utm_source=copy
MMU解读的更多相关文章
- U-Boot GOT表分析和u-boot.lds解读
转自:http://blog.sina.com.cn/s/blog_70dd16910100zab6.html u-boot-2010.09/arch/powerpc/cpu/mpc86xx/star ...
- 深入解读Linux进程调度Schedule【转】
转自:https://blog.csdn.net/Vince_/article/details/88982802 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文 ...
- 鸿蒙OS的系统调用是如何实现的? | 解读鸿蒙源码
本文将首先带您回顾"系统调用"的概念以及它的作用,然后从经典的Hello World开始,逐行代码层层分析--鸿蒙OS的系统调用是如何实现的. 写在前面 9月10号 华为开发者大会 ...
- SDWebImage源码解读之SDWebImageDownloaderOperation
第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
- SDWebImage源码解读 之 NSData+ImageContentType
第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...
- SDWebImage源码解读 之 UIImage+GIF
第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...
- SDWebImage源码解读 之 SDWebImageCompat
第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...
- SDWebImage源码解读_之SDWebImageDecoder
第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...
- SDWebImage源码解读之SDWebImageCache(上)
第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...
随机推荐
- 【BZOJ】3400: [Usaco2009 Mar]Cow Frisbee Team 奶牛沙盘队(dp)
http://www.lydsy.com/JudgeOnline/problem.php?id=3400 既然是倍数我们转换成mod.. 设状态f[i][j]表示前i头牛modj的方案 那么答案显然是 ...
- WebSocket入门教程(五)-- WebSocket实例:简单多人聊天室
from:https://blog.csdn.net/u010136741/article/details/51612594 [总目录] WebSocket入门教程--大纲 [实例简介] ...
- 一个简单RPC框架是怎样炼成的(VI)——引入服务注冊机制
开局篇我们说了.RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注冊 RPC消息处理 接下来处理RPC服务的注冊机制.所谓注冊机制,就是Server须要声明支持哪些rpc方法 ...
- sql中between and 用法
SQL中 between and是包括边界值的,not between不包括边界值,不过如果使用between and 限定日期需要注意,如果and后的日期是到天的,那么默认为00:00:00 例如: ...
- 51NOD 1013(3的幂的和)
题目链接:传送门 题目大意:求(3^0+3^1+3^2+3^3+...+3^n)%1e9的值 题目思路:乘法逆元裸题 #include <iostream> #include <cs ...
- mysql如何判断一个字符串是否包含另外一个字符串?
转自:http://blog.csdn.net/hechurui/article/details/49278493 判断子字符串在父字符串当中的索引: SELECT LOCATE("b&qu ...
- @Override must override a superclass method 有关问题解决
1.Java开发环境时 如果在使用Eclipse开发Java项目时,在使用 @Override 出现以下错误: The method *** of type *** must override a s ...
- No transactional EntityManager available; nested exception is javax.persistence.TransactionRequiredException: No transactional EntityManager available
参考地址:http://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/ ...
- jQuery选择器概览
层级 ancestor descendant parent > child prev + next prev ~ siblings 基本筛选器 :first :not(selector) :ev ...
- salt常用命令、模块、执行
一.salt常用命令 salt 该命令执行salt的执行模块,通常在master端运行,也是我们最常用到的命令 salt [options] '<target>' <function ...