程序是如何映射到内存中的

概述

本文出自《程序员的自我修养——链接、装载与库》,属于个人学习笔记

在早期的的计算机中,程序是直接运行在物理内存上的,也就是说程序在运行时所访问的地址都是物理地址。当然,如果一个计算机同时只运行一个程序,那么只要程序要求的内存空间不超过物理内存大小,运行就不会有问题。但是为了更有效地利用硬件资源,我们有时候需要同时运行多个程序。那么很明显的一个问题是,如何将计算机上有限的物理内存分配给多个程序使用。

早期内存分配模型.jpg

假设我们的计算机内有100MB内存,程序A运行需要10MB,程序B运行需要80MB,程序C需要30MB。如果我们要同时运行程序A和B,那么只需要把程序0 ~ 10MB分配给A,程10 ~ 90MB分配给程序B就可以了。但是这种分配策略存在很多问题。

  • 地址空间不隔离
    所有程序都直接访问物理地址,程序所使用的的内存空间不是相互隔离的。恶意程序可以恶意的改写其他程序的内存数据,已达到破坏的目的;有些非恶意的也有可能不小心修改了其他程序的数据,就会影响其他程序的正常运行,给应用程序带来安全隐患。
  • 内存使用效率低
    由于没有有效的内存管理机制,通常一个程序执行时,监控程序就会将整个程序装入内存中然后开始执行。以上情况中,在运行A和B的情况下,如果我们忽然又要运行程序C,那么这时候的内存空间肯定是不够的,这时候我们只能是先将其他程序暂时写到磁盘里面去,等要用到了在读回来。由于程序所需要的空间是连续的,那么如果我们将程序A换到磁盘所释放出的内存空间是不够的,所以只能将B换出到磁盘,然后将C读入到内存开始运行。在这个过程中有大量的数据在换入换出,导致效率十分低下。
  • 程序运行的地址不确定
    因为程序每次需要装入运行时,我们都需要给他重新从内存中分配出一块足够大的空闲内存区域,这个空闲区域的位置是不确定的,这个程序的编写造成了一定的麻烦,因为程序在编写时,他访问数据和指令跳转时的目标地址很多都是固定的,这涉及程序的重定位问题。

解决这个问题的思路是:增加中间层,即使用一种间接的地址访问方法。我们把程序给出的地址看做是一个虚拟地址(Virtual Address),然后通过某些映射的方法,将这个虚拟地址转换成实际的物理地址。这样,只要我们管理好虚拟地址到物理地址的映射过程,就可以保证任意一个程序所能够访问的物理内存区域跟另外一个程序相互不重叠,已达到地址空间隔离的目的。

分段

关于地址隔离的问题,最开始人们使用的一种叫做分段(Segmentation)的方法,基本思路是把一段与程序所需要的内存空间大小的虚拟空间映射到某个地址空间。比如程序A需要10MB的内存空间,那么我们假设有一个地址从0x00000000到0x00A00000的10MB大小的一个假想空间,也就是虚拟空间,然后我们从实际的内存中分配一个相同大小的物理地址空间,假设物理地址是0x00100000开始到0x00B00000结束的一块空间。把然后我们把两块相同的地址空间一一映射,即虚拟空间的每个字节对应物理空间中的每个字节。这个映射过程有软件来设置,比如操作系统来设置这个映射函数,实际的地址转换有硬件来完成。比如当程序A访问虚拟地址0x00001000时,CPU会将这个地址转换成实际的物理地址0x00101000。那么比如程序A和程序B在运行时,他们的虚拟地址空间和物理地址空间映射关系如下图所示:

分段内存模型.jpg

分段的方法基本解决了上面提到的3个问题中的第一个和第三个。首先它做到了地址隔离,因为程序A和程序B分别被映射到两块不同的区域,他们之间没有任何重叠。程序只能访问自己虚拟地址空间范围内。如果程序A访问虚拟空间地址超过了0x00000000 ~ 0x00A00000这个范围,那么硬件就会根据地址映射表判断这是非法访问,拒绝这个请求,并将这个请求报告给操作系统或相关监控程序,由它来决定如何处理。再者,对于每个程序来说,无论他们被分配到物理地址的哪个区域,对于程序来说都是透明的,程序不需要关心物理地址的变化,它们只需要按照0x00000000 ~ 0x00A00000的虚拟地址空间来编写程序、放置变量,所以程序不再需要重定位。

但是分段的这种方法还是没有解决我们的第二个问题,即内存使用效率的问题。分段对内存区域的映射还是按照程序为单位,如果内存不足,被换入换出到磁盘的还是整个程序,这样势必会造成大量的磁盘访问操作,从而严重影响速度,这种方法还是显得比较粗糙,粒度较大。事实上,根据程序的局部性原理,当一个程序在运行时,在某个时间内它只是频繁地用到了一小部分数据,也就是说,程序的很多数据其实在一定的时间内都是不会被用到的。人们很自然就想到了更小粒度的内存分割和映射方案,使得程序的局部性原理得到充分的应用,提高内存的使用效率。这种方法就叫做分页(Paging)。

分页

分页的基本方法是把地址空间认为地分成固定大小的页,每一页的大小由硬件决定,或硬件支持多种大小的页,有操作系统选择决定页的大小。
下面我们就来看一个简单地例子,如下图所示,每个虚拟空间有8页,每页大小为1KB,那么虚拟地址空间就是8KB。我们假设该计算机拥有13条地址线,即拥有2^13的物理寻址能力,那么理论上物理空间可以多达8KB。

分页模型.jpg

我们把进程的虚拟地址空间按页分割,把常用的数据和代码页装载到内存中,把不常用的代码和数据保存在磁盘中,当需要用到的时候再从磁盘里面读出来即可。如图所示,我们假设有两个进程Process1和Process2,它们进程中的部分虚拟页面被映射到了物理页面,比如VP0、VP1和VP7映射到PP0、PP2和PP3;而部分页面却在磁盘中,比如VP2和VP3位于磁盘的DP0和DP1中;另外还有一些页面如VP4、VP5和VP6可能尚未被用到或者访问到,它们暂时处于未使用的状态。在这里,我们把虚拟空间的页就叫虚拟页(VP, Virtual Page),把物理内存中的页叫物理页(PP, Physical Page),把磁盘中的页叫做磁盘页(DP, Disk Page),页映射关系就叫页表。图中的线表示映射关系,我们可以看到虚拟空间有些页被映射到同一物理页,这样就实现了内存共享。
图中Process1的VP2和VP3不在内存中,但是当进程需要用到这两个页的时候,硬件会捕获这个消息,就是所谓的页错误(Page Fault),也叫页中断,然后操作系统接管进程,负责将VP2和VP3从磁盘里面读出来并装入内存中,然后将内存中的这两个页与VP2和VP3之间建立映射关系。以页为单位来存取和交换这些数据非常方便,硬件本身就支持这种以页为单位的操作方式。通过这种分页的方式,大大提高了内存的使用效率,能同时支持多个应用运行而且不需要把整个程序都装载到内存里面,可以按需加载。
页映射还有一个好处就是可以保护操作系统和保护进程。简单说就是每个页可以设置权限属性,谁可以修改谁可以访问,而只有操作系统有权限修改这些属性,那么操作系统就可以做到保护自己和保护进程。
虚拟内存的实现需要依靠硬件的支持,对于不同的CPU来说是不同的。但是几乎所有的硬件都采用一个叫内存管理单元(Memory Management Unit, MMU)的部件来进行页映射,如下图所示:

MMU原理.jpg

在页映射模式下,CPU发出的是Virtual Address, 即我们程序看到的是虚拟地址。经过MMU转换以后就变成了Physical Address。一般MMU都集成在CPU内部了,不会以独立的部件存在。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,082评论 5 464
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,231评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,047评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,977评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,893评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,976评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,605评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,888评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,906评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,732评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,513评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,980评论 3 301
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,132评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,447评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,027评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,232评论 2 339

推荐阅读更多精彩内容