您的位置:首页 > 职场人生

读书笔记——《程序员自我修养》——内存不够怎么办?

2015-07-30 09:28 393 查看

内存不够怎么办?

在写单片机程序的时候,整个程序是一个死循环,该程序可以任意调用物理内存及硬件资源。当然如果计算机操作系统同一时间也只运行一个程序,且这个程序要求的内存空间不超过物理内存,也就不会有接下来的困扰了。

那么在现在的多任务操作系统中如何将有限的物理内存分配给多个程序(进程)使用呢?

假设计算机有128M内存, 程序A需要10MB,程序B需要100MB,程序C需要20MB。如果我们同时运行程序A和程序B,简单的想法是物理内存的0~10M分配给A, 物理内存的10M ~110M 分配给B,这样就能实现A、B两个程序同时运行。



(图一)

仔细分析就会发现问题很多:

地址空间不隔离

如果所有程序都能直接访问物理地址每个程序之间的内存空间不隔离,恶意程序或着程序的bug就会修改其他程序的数据,在用户看来就是一个程序的运行会导致其他程序的运行失败,这个是不允许的。

内存的使用效率低

在没有有效的内存管理机制下,要执行一个程序通常需要把整个程序都装载到内存中然后再开始执行。如果忽然要运行程序C,那么这时内存空间已经不够用了,我们有一个办法就是把其他程序的数据暂时写回磁盘里,等到需要的时候在读出来,如图一的例子,如果将A换出到磁盘上所释放的内存空间是不够用的所以只能将程序B的100M占用的内存空间都释放出来,显然可以看出大量的数据换入换出导致内存的使用效率十分低下。

程序运行的地址不确定

程序每次装入运行时都要给它从内存中分配一块足够大的空间区域,这个空间的地址不确定,这个程序的编写造成了极大的麻烦。

为了解决上诉问题就产生了赫赫有名的虚拟地址,每个程序不用自己分配内存,也不用考虑别的程序在内存中占用的情况,在程序看来就好像自己完全占有了所有内存一样,但其实是它占用了分配给它的虚拟内存,而每个进程只能访问自己的地址空间。

实现方法就是把程序给出的地址看成虚拟地址,然后通过某种映射方法(硬件MMU实现)将虚拟地址转化成实际的物理地址,只要控制虚拟地址到实际物理地址的映射过程就可以保证任一程序能够访问的物理内存区域跟其他程序相互不重叠,达到地址隔离的效果。

问题来了,物理地址少虚拟地址大,不够分怎么办?
于是产生了分段的思想:
基本思想是把程序需要的内存空间大小的虚拟空间映射到某个地址空间。如图二,两个程序A和B都单独的运行在内存中相互不干扰,而且是经过虚拟地址到物理地址的映射,程序使用的是虚拟地址这样 上诉三个问题中的地址隔离和地址空间不确定都得到了解决。



(图二)

问题又来了,内存使用效率低如何解决?
但分段的这种方法还没有解决内存使用效率的问题,分段对内存区域的映射还是按照程序为单位,如果内存不足将被换入到磁盘的都是整个程序,这样造成了大量的IO访问。
实际上当一个程序运行时,在某个时段,它只是频繁的用到了一小部分数据,也就是说,程序的很多数据其实在一个时间段内都不会被用到。那么就自然的想到了跟小粒度的内存分割和映射方法,使程序的局部性原理得到充分的利用,大大提高了内存的使用效率,这种方法就是分页

几乎所有PC上的操作系统都是用4KB的页大小。如果我们的PC使用的是32位的虚拟地址空间,也就是4GB,那么按4KB分页就分为了1048576个页,物理地址空间也是同样的分法。

假设虚拟空间有8页,然而物理空间只有6页,那么需要把常用的数据和代码装载到内存中,把不常用的代码和数据保存在磁盘里,当需要用的时候再把它从磁盘里取出来即可。假设有两个进程Process1 和 Process2,进程中的部分常用的虚拟页被映射到了物理内存上(红色),而有部分不常用的虚拟页被映射到了磁盘上(绿色),而还有些虚拟页暂时处于未使用状态(蓝色)。
在Process1中VP2和VP3不在内存中,但当进程需要用到这两个页的时候硬件会捕获这个消息,产生页错误(Page Fault),然后操作系统接管进程,负责将VP2和VP3从磁盘中读取出来并装入内存,然后将内存中的这两个页与VP2和VP3之间建立映射关系。
图三中有些虚拟地址被映射到同一个物理页,这样可以实现共享内存。



(图三)

概念:
虚拟页(VP Virtual Page)
物理页 (PP Physical Page)
磁盘页 (DP Disk Page)

虚拟内存的实现要依靠硬件支持,但几乎所有的硬件都采用一个叫MMU的部件来进行映射



CPU 端看到的是虚拟地址,经过MMU转换变成物理地址,一般MMU都集成在CPU内部。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: