理解CPU内存管理
概述:从设计层面理解CPU的内存模式,包括段式内存管理、页式内存管理以及虚拟化扩展内存管理。实际上,硬件支持与软件实现从来就不是能分开讲的,比如,Intel CPU架构师在选择CPU的硬件特性时,必然会站在软件的角度审视该特性。目前,硬件实现的许多特性完全可以由软件方式实现,但为何非要设计成硬件实现方式,其原因或许是因为硬件实现有助于系统整体的性能提高,亦或许受研究者的个体偏好等非技术性因素影响,本文不做深究。
CPU处理器的内存管理提供了段式内存管理和页式内存管理两种技术,OS在借助该内存管理技术实现了系统底层的内存管理功能。
我们知道,由于内存(RAM,主存,半导体材料)的访问速度远远超过硬盘存储介质(磁性材料),所以内存负责与CPU直接交互,程序运行之前其数据和代码需要被加载到内存之中。那么问题来了,“上帝”将待执行的程序加载到内存之中就OK了,为什么还要通过段/页式内存管理方式管理内存呢?要知道段页式内存管理技术会将一个给定的“内存地址”变来变去,非常繁琐,导致"当前程序“理解的内存地址与实际的物理内存地址的对应关系并不直观,为什么CPU/OS要采用这类内存管理方式呢?
如果”当前程序“理解的内存地址为A,对应的物理内存也是A,世界该是多么的直白……
我在学习操作系统之初就思考过这个问题,后来阅遍经卷、参悟CPU架构、自己开始实现一个OS内核之后才对这个问题理解得越来越深刻。
首先要知道一点,OS实现段/页式内存管理的说法存在一定的误导性,更准确的说法应该是,现代CPU架构设计支持了段页式内存管理设计,OS作为一个纯软件实体,如果想基于CPU提供的技术支持正常运行,就必须对段页式内存管理技术做出表态:用还是不用。实际上,段式管理是必须要有的,页式管理是可选的。
那么,为什么CPU架构要支持该类内存管理技术?这个问题的理解又要转到”软实体“的角度。
打个比方,我作为土豪一枚,我的机器配置了50G物理内存,OS欲将待运行的程序加载到这50G内存里面,该加载到内存的哪部分,或如何利用50G内存呢?
方式一:将整个程序全部加在到内存中,这50G内存都是该程序自己的,随便用!
这种内存管理方式最大的缺点就是,OS不能实现我们所说的”多任务“,即很难”同时“执行多个程序。如果用这种内存管理方式实现多任务支持,只能这样:OS加载程序A,A运行了0.1s后被暂停,OS将A的当前状态保存到磁盘,然后加载程序B,B运行0.1s后被暂停并被保存状态到磁盘,OS加载A,恢复A的执行状态并执行A 0.1s...
作为一种原始的内存使用和多任务方式,该方案粗暴、低效、资源浪费……你想怎么批评它就怎么批评它!
方式二:将50G按10G分成5部分,OS拿出其中四部分即40G空间加载4个程序并运行,任务切换只需要切换当前的CPU状态而不必重新加载目标程序。咦……OS瞬间支持4任务了……但是如果想支持8任务、10任务呢?难道针对一个不同的多任务需求需要定制不同的多任务OS吗?另外,任务之间的内存隔离也有问题,在0-10G内存空间里的程序可以直接访问到其他3个任务的内存空间数据(如果没有而外的硬件防护的话),好像安全性不敢保证,因为CPU在执行指令时如不借助”助手“将无法判断某个内存位置访问是否合法。
但是,这种方案确实有些进步,因为这种内存管理方式可以简单满足多任务需求了,而且,对比现代内存管理技术,该方案可以称之为”硬件级固定长度的段式内存管理“了。
方式三:现在,需要解决方式二的缺点,实现任意多任务和内存访问保护。
CPU架构师这样考虑(我猜的)的:
如果我把内存不按照定长分割,而是根据待加载的程序的大小,使用智能算法决定为它分配多大内存,这不就可以更好的实现多任务了嘛!
理论上只要物理内存足够大,就可以支持同时运行任意数量的任务。
程序间的内存保护(最起码任务程序不能越界访问其他任务的内存)该如何实现呢?
CPU架构师这样考虑(我猜的)的:
CPU在加载程序后,当前程序的内存首地址(基址)和内存长度保存到一张表里面,此时程序所理解得内存地址在CPU看来永远是一个相对于当前基址的偏移地址。
这样,程序访问内存是提供的内存地址紧紧是个CPU眼中的偏移而已,CPU就可以查表检查该偏移是否超过内存长度。
如果偏移合法,基址加偏移就可以得到真实的物理地址,然后取得数据;如果偏移不合法,CPU拒绝访问数据,并抛出异常。
如果你读过其他资料已经对段式内存管理有所了解,那么你应该会看出,方式三正是段式内存管理技术的雏形,CPU用到的表就是GDT/LDT。
待续。。。
理解CPU内存管理的更多相关文章
- Intel X86 32位CPU内存管理----《Linux内核源码情景分析》笔记(一)
Intel X86 32位CPU内存管理 在X86系列中,8086和8088是16为处理器,而从80386开始为32为处理器,80286则是该系列从8088到80386,也就是16位处理器到32位处理 ...
- 深入理解Android内存管理原理(六)
一般来说,程序使用内存的方式遵循先向操作系统申请一块内存,使用内存,使用完毕之后释放内存归还给操作系统.然而在传统的C/C++等要求显式释放内存的编程语言中,记得在合适的时候释放内存是一个很有难度的工 ...
- 你应该这样理解JVM内存管理
在进行Java程序设计时,一般不涉及内存的分配和内存回收的相关代码,此处引用一句话: Java和C++之间存在一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外的人想进去,墙里面的人想出来 ,个人从这 ...
- OC 知识:彻底理解 iOS 内存管理(MRC、ARC)
1. 什么是内存管理 程序在运行的过程中通常通过以下行为,来增加程序的的内存占用 创建一个OC对象 定义一个变量 调用一个函数或者方法 而一个移动设备的内存是有限的,每个软件所能占用的内存也是有限的 ...
- 深入理解 Linux 内存管理
1. 内存地址 以Intel的中央处理器为例,Linux 32位的系统中.物理内存的基本单位是字节(Byte),1个字节有8个二进制位. 每一个内存地址指向一个字节,内存地址加1后得到下一个字节的地址 ...
- 深入理解C++内存管理机制
关于C++的内存处理,可分为三大块,分别是: (一)内存管理机制 (二)内存泄露处理 (三)内存回收机制 这篇文章将就(一)内存管理机制 进行深入探讨,如有错误欢迎大家指正. C++的内存管理也可细分 ...
- 深入理解Aarch64内存管理
本文是对learn_the_architecture_-_aarch64_memory_management的部分翻译和个人注解.个人英文水平有限,若有翻译不当,欢迎加我私人微信LinuxDriver ...
- [转载]对iOS开发中内存管理的一点总结与理解
对iOS开发中内存管理的一点总结与理解 做iOS开发也已经有两年的时间,觉得有必要沉下心去整理一些东西了,特别是一些基础的东西,虽然现在有ARC这种东西,但是我一直也没有去用过,个人觉得对内存操作 ...
- Spark内存管理机制
Spark内存管理机制 Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行 ...
随机推荐
- How Much Work Does it Take to be a Successful Mathematician?
http://mathoverflow.net/questions/9799/how-much-work-does-it-take-to-be-a-successful-mathematician# ...
- 对同一元素设置overflow-x:hidden,overflow-y:visible;属性值不生效
作者:孙志勇 微博 日期:2016年12月5日 一.时效性 所有信息都具有时效性.文章的价值,往往跟时间有很大关联.特别是技术类文章,请注意本文创建时间,如果本文过于久远,请读者酌情考量,莫要浪费时间 ...
- 在VS中安装EF和项目引用EF
1.通过Visual Studio安装NuGet (1). 打开Visual Studio扩展管理器 (2). 选择联机库,并在搜索中写入NuGet,然后点击搜索结果中NuGet Packag ...
- Oracle RMAN 清除归档日志
在开发环境及UAT环境经常碰到需要清除归档日志的情形,对于这个问题方法有很多.可以直接使用rm方式清除归档日志,也可以使用find命令来查找符合条件的记录来清除归档日志,或者直接写个shell脚本来搞 ...
- 在Linux下怎么确定哪个网卡对应哪个接口?
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...
- cocos2d-x CCTableView
转自:http://www.cnblogs.com/dcxing/archive/2013/01/16/2862068.html CCTableView在游戏中一般用在背包这样场景或层中,当然也不止这 ...
- python flask 部署
flask在开发的时候,经常启动本身进行调试(本身可以设置监听的端口,例如 在app.run(port=8088),当然默认不设置端口为5000). 但生产环境经常使用uswgi充当flask的宿主, ...
- range-bar
https://github.com/edmodo/range-bar
- DataTable转换为List<Model>的通用类
在开发中,把查询结果以DataTable返回很方便,但是在检索数据时又很麻烦,没有模型类型检索方便. 所以很多人都是按照以下方式做的: // 获得查询结果DataTable dt = DbHelper ...
- MySQL server version for the right syntax to use near ‘USING BTREE
转自:http://www.douban.com/note/157818842/ 有时导入mysql会提示如下错误: C:\Users\liqiang>mysql -uroot -paaaaaa ...