iOS内存不够怎么办?-底层原理

在早期的计算机中,程序是直接运行在物理内存上的,也就是说:程序在运行时访问的地址就是物理地址。这样也就是单运行的时候没有什么问题!但是,计算机会有多到程序、分时系统和多任务,当咱们可以同时运行多个程序时,CPU的利用率将会比较高。那么有一个很是严重的问题:如何将计算机的有限的物理内存分配给多个程序使用程序员

假设咱们计算有128MB内存,程序A须要10MB,程序B须要100MB,程序C须要20MB。若是咱们须要同时运行程序A和B,那么比较直接的作法是将内存的前10MB分配给程序A,10MB~110MB分配给B。数组

但这样作,会形成如下问题:函数

  • 当多个程序须要运行时,必须保证这些程序用到的内存总量要小于计算机实际的物理内存的大小。学习

  • 进程地址空间不隔离,因为程序是直接访问物理内存的,因此每个进程均可以修改其余进程的内存数据,设置修改内核地址空间中的数据,因此有些恶意程序能够随意修改别的进程,就会形成一些破坏操作系统

  • 内存使用效率低 内存空间不足,就须要将其余程序展现拷贝到硬盘当中,而后将新的程序装入内存。然而因为大量的数据装入装出,内存的使用效率会很是低code

  • 程序运行的地址不肯定;由于内存地址是随机分配的,因此程序运行的地址也是不正确的cdn

解决这几个问题的思路就是使用咱们很是牛逼的方法:增长中间层 - 即便用一种间接的地址访问方式。blog

把程序给出的地址看作是一种虚拟地址,而后经过某种映射,将这个虚拟地址转化到实际的物理地址。这样,只须要控制好映射过程,就能保证程序所能访问的物理内存区域跟别的程序不重叠,达到空间隔离的效果。进程

隔离

普通的程序它只须要一个简单的执行环境一个单一的地址空间有本身的CPU。 地址空间比较抽象,若是把它想象成一个数组,每个数组是一字节,数组大小就是地址空间的长度,那么32位的地址空间大小就是2^32=4294967296字节,即4G,地址空间有效位是0x00000000~0xFFFFFFFF。 地址空间分为两种:内存

  • 物理空间:就是物理内存。32位的机器,地址线就有32条,物理空间4G,但若是只装有512M的内存,那么实际有效的空间地址就是0x00000000~0x1FFFFFFF,其余部分都是无效的。

  • 虚拟空间:每一个进程都有本身独立的虚拟空间,并且每一个进程只能访问本身的空间地址,这样就有效的作到了进程隔离。

分段

基本思路: 把一段与程序所须要的内存空间大小的虚拟空间映射到某个地址空间。虚拟空间的每一个字节对应物理空间的每一个字节。这个映射过程由软件来完成。

好比A须要10M,就假设有0x000000000x00A00000大小的虚拟空间,而后从物理内存分配一个相同大小的空间,好比是0x001000000x00B00000。操做系统来设置这个映射函数,实际的地址转换由硬件完成。若是越界,硬件就会判断这是一个非法访问,拒绝这个地址请求,并上报操做系统或监控程序。

这样一来利用:分段的方式能够解决以前的个(地址空间不隔离)和第三个问题(程序运行地址不肯定)

  • 首先作到了地址隔离,由于A和B被映射到了两块不一样的物理空间,它们之间没有任何重叠,若是A访问虚拟空间的地址超过了0x00A00000这个范围,硬件就会判断这是一个非法的访问,并将这个请求报告给操做系统或者监控程序,由它决定如何处理。

  • 再者,对于每一个程序来讲,不管它们被分配到地址空间的哪个区域,对于程序来讲都是透明的,它们不须要关心物理地址的变化,它们只要按照从地址0x000000000x00A00000来编写程序、放置变量,因此程序不须要重定位。

第二问题内存使用效率问题依旧没有解决。

可是分段的方法没有解决内存使用效率的问题。分段对于内存区域的映射仍是按照程序为单位,若是内存不足,被换入换出的磁盘的都是整个程序,这样势必会形成大量的磁盘访问操做,从而严重影响速度,这种方法仍是显得粗糙,粒度比较大。事实上根据程序的局部性原理,当一个程序正在运行时,在某个时间段内,它只是频繁用到了一小部分数据,也就是说,程序的不少数据其实在一个时间段内是不会被用到的。人们很天然地想到了更小粒度的内存分割和映射方法,使得程序的局部性原理获得充分利用,大大提升了内存的使用率。这种方法就是分页。

分页

分页的基本方法是把地址空间人为得等分红固定大小的页,每个页的大小由硬件决定,或硬件支持多种页的大小,由操做系统选择决定页的大小。 目前几乎全部PC的操做系统都是用4KB大小的页。咱们使用的PC机是32位虚拟地址空间,也就是4GB,按4KB分页,总共有1048576个页。

那么,当咱们把进程的虚拟地址空间按页分割,把经常使用的数据和代码装载到内存中,把不经常使用的代码和数据保存在磁盘里,当须要用到的时候再把它们从磁盘里取出便可。图中的线表示映射关系,咱们能够看到虚拟空间有些页被映射到同一个物理页,这样就能够实现内存共享。 虚拟页,物理页,磁盘页根据内存空间不同而区分

咱们能够看到Process 1 的VP2和VP3不在内存中,可是当进程须要用到这两个页的时候,硬件就会捕获到这个消息,就是所谓的页错误(Page Fault),而后操做系统接管进程,负责将VP2和VP3从磁盘读取出来装入内存,然都将内存中的这两个页和VP2和VP3创建映射关系。以页为单位存取和交换数据很是方便,硬件自己就支持这种以页为单位的操做方式。

  • 保护页也是页映射的目的之一,简单地说就是每一个页能够设置权限属性,谁能够修改,谁能够访问,并且只有操做系统有权修改这些属性,那么操做系统就能够作到保护本身和保护进程。

  • 虚拟存储的实现须要硬件支持,几乎全部CPU都采用称为MMU的部件来进行页的映射:

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

这篇文章是底层编译连接的开门红,这里很是感谢《程序员的自我修养-连接、装载与库》这本书的大力分享,强烈推荐学习

相关文章
相关标签/搜索