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(上)
第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...
随机推荐
- [转]使用TeamCity对项目进行可持续集成管理(一)
一.可持续集成管理 持续集成,CI:即Continuous integration. 可持续集成的概念是基于团队(小组)协作开发而提出来的,为了提高团队开发效率与降低集成风险(早发现,早解决.晚发现, ...
- Deep Learning阅读资料
入门基础阅读:http://www.cnblogs.com/avril/archive/2013/02/08/2909344.html 书籍推荐:http://blog.chinaunix.net/u ...
- js事件循环机制(Event Loop)
javascript从诞生之日起就是一门 单线程的 非阻塞的 脚本语言,单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务,非阻塞靠的就是 event lo ...
- nginx搭建文件服务器
在部署了各种应用后,产生的日志文件,需要在线下载查看,不用每次登陆服务器去拿: 这里,因为服务器部署了很多的应用程序,可以建一个主目录mylog,在主目录里用软连接将需要的各个日志文件夹都建好连接 l ...
- 编写高质量代码--改善python程序的建议(三)
原文发表在我的博客主页,转载请注明出处! 建议十三:警惕eval()的安全漏洞 相信经常处理文本数据的同学对eval()一定是欲罢不能,他的使用非常简单: eval("1+1==2" ...
- 我的JavaScript笔记--数据类型,预编译,闭包
在我们js中存储数据的空间可以分为两种,堆内存和栈内存 堆内存:我们定义的那些引用数据类型的数据都会在堆内存中开辟空间. 栈内存:我们运行的js代码还有我们定义的基本数据类型,都直接在栈内存中存储 ...
- windows安装oracle11g
windows上安装oracle11g 1.下载Oracle 11g R2 for Windows的版本 下载地址:https://www.oracle.com/technetwork/datab ...
- shared_ptr & weak_ptr
shared_ptr <1> 类模板说明 namespace boost { class bad_weak_ptr: public std::exception; template< ...
- 【BZOJ4503】两个串 FFT
[BZOJ4503]两个串 Description 兔子们在玩两个串的游戏.给定两个字符串S和T,兔子们想知道T在S中出现了几次, 分别在哪些位置出现.注意T中可能有“?”字符,这个字符可以匹配任何字 ...
- 巨蟒python全栈开发数据库前端7:jQuery框架
每个人的标准不同,看法等等,认识,价值观有所不同,促成了这些矛盾. 1.select例子 <!DOCTYPE html> <html lang="en"> ...