虚拟内存(Virtual Memory)
虚拟内存的实现思想:
- 将外存储器的部分空间作为内存的扩展
- 当内存不足时,系统将按照一定算法自动挑选优先级低的数据块,并把它存储到磁盘中
- 后续如果需要用到磁盘中的这些数据,系统将产生“缺页”指令,然后把它们交换会内存
- 这些操作都由操作系统内核自动完成,对上层应用“完全透明”
三种不同的地址空间:
1、逻辑地址(Logical Address)
也成相对地址,是程序编译后所产生的地址,逻辑地址有两部分组成:
- Segment Selector(段选择子)
用于描述逻辑地址所在的段,16bit。 - Offset
用于描述段内的偏移值,32bit。
2、线性地址(Linear Address)
线性地址是逻辑地址经过分段机制转换后形成的,其基本思想是:
- 根据段选择子中的TI字段,得知段描述符存储在GDT或LDT中
- 通过GDTR/LDTR获得GDT/LDT的存储地址
- 根据段选择子中的INDEX字段,到GDT/LDT中查找到对应的段描述符
- 根据段描述符获得此段的基地址
- 由基地址+段内便宜地址得到线性地址
3、物理地址(Physical Address)
它指机器真实的物理内存所能所表示的地址空间范围。当系统开启了分页机制后,线性地址需要经过一次转换才是物理地址。
- 页
与分段机制不同的是,分页机制的操作对象是固定大小的内存块,称为“页”,页的大小为4KB - 页框
与页的概念相对,页框是对物理内存的最小操作单位,显然页和页框大小必须完全一致,即4KB。
内存保护
最初的操作系统中,并没有严格的内存保护机制,对于内存的访问完全由程序编写。后来人们逐渐认识到内存保护的必要性,并列入内存管理的重点。
内存分配与回收
1、保证硬件无关性
每个硬件平台的物理内存型号、大小甚至架构等可能都各不相同,这种差异决不能体现在应用程序上,操作系统应尽可能实现向上的“透明”。
2、动态分派内存和回收
3、内存碎片
内核既要保证内存分配的合理性,也要考虑整体机制的高效性。在Android系统中,内存的分配与回收分为两个方向:
- Native层
本地层的程序基本上是由C/C++编写,动态分配的内存需要人工管理。 - Java层
Java相对于C在内存管理上做了很多努力,提供了自动管理内存,但是Java本身不是万能的,在开发过程中还是要遵循良好的内存使用规范。
进程间通讯——mmap
mmap可以将某个设备或者文件 映射到应用进程的内存空间中,这样访问这块内存就相当于对设备/文件进行读写,而不再通过read()和wirte()。通过映射同一块物理内存来共享内存即可实现进程间通讯,这种方式因为减少了数据复制次数,一定程度上提高了进程间通讯的效率。
Android匿名共享内存
Anonymous Shared Memory(简称Ashmem)是Android特有的内存共享机制,它可以将制定的物理内存映射到各个进程自己的虚拟地址空间中,从而便捷地实现进程间的内存共享。
参考资料
- 深入理解Android内核设计思想. 林学森。