多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
现代操作系统基本都采用虚拟内存管理的方式来管理每个进程对内存的访问,对进程采用虚拟内存的方式进行管理可以避免不同的进程访问相同的物理内存而造成程序的紊乱。每个进程都维护独立的一份虚拟地址,例如在32位操作系统中进程A有4GB的虚拟地址可以使用,进程B也有4GB的虚拟地址可以使用,**因此不同进程彼此之间访问是相互隔离的。** **注意,进程中的地址称为“逻辑地址”,也称“虚拟地址”,需要转化为实际的内存设备的“物理地址”才能够使用。** :-: ![](https://img.kancloud.cn/26/bf/26bfab47c01eb77fbe9b343d4100cef2_193x424.png) 对于内存的管理一般有分段和分页两种方式。   ## 内存分段 分段式管理将进程中的内存分为不同的段,例如可以分为代码段、数据段、栈段、堆段等,这也是最早的内存管理方式。这种方式通过**段表**结构来将虚拟内存映射成物理内存。段表中的段表项由(段号,物理段号)组成。虚拟内存的地址由(段号,偏移地址)组成。 :-: ![](https://img.kancloud.cn/1e/90/1e90c4c51b98becd72ff1a4619cbfb83_945x665.png) 【参考:小林图解系统】 采用内存分段的方式有如下的两个问题: 1. 容易产生内存碎片:内存分段的方式是完整的将应用程序加载进内存中,而且内存的分配还是一大段连续的,这样就很容易造成一小块内存一小块内存存在的问题,这就是内存碎片。 2. 内存交换效率低:Linux系统中有一块swap的磁盘区域就是用于当内存不够用的时候将内存换到磁盘中,由于分段式连续且一般都是比较大的一块空间,所以交换的效率就比较低。   ## 内存分页 这是现在操作系统用得比较多的内存管理方式,将内存分为以4KB大小为单位的内存页,这样在内存不够用的时候进行交换时也比较快;同时由于每页都是比较小的连续4KB的内存空间,也不容易造成内存碎片。 内存分页使用页表结构来保存虚拟内存到物理内存的映射关系,通过MMU(内存管理单元)来处理这种映射关系,内存分页的映射过程如下: :-: ![](https://img.kancloud.cn/de/1e/de1e3cab140342dfb0e4dcd9543351e6_946x684.png) 虚拟地址组成:(页号、页内偏移量) 页表组成:(虚拟页号、物理页号) **每个进程都有单独的一份页表结构来保存进程内虚拟内存到物理内存的映射关系。** 现在操作系统多采用多级页表的结构,其结构如下: :-: ![](https://img.kancloud.cn/a6/02/a60298a93632924d79e4211a392747d1_918x630.png) 由于“程序局部性原理”,可以使得每次不用生成太多的二级页表,只需要生成加载进内存的那部分内存空间的二级页表就行了,**注意一级页表的范围是要覆盖所有物理内存的大小的。** 为了避免地址映射的时候多次读取内存,因此在CPU内存封装了TLB(快表)缓存结构,用来缓存最近访问过的页表项。   ## Linux的内存管理方式 由于CPU现代CPU采用分段+分页的方式来管理内存的,Linux系统也只能跟随的CPU来实现。但是Linux将整个物理内存都当成一个段,这样的话就屏蔽了分段,只用到分页来管理内存。 Linux一般将一个进程的虚拟内存分为**用户空间与内核空间。**例如32位操作系统将虚拟内存分为1GB的内核空间和3GB的用户空间 :-: ![](https://img.kancloud.cn/54/c2/54c2e030b7c3fcdb8c7957d19bae798b_918x372.png) 对于每个进程其3GB的用户空间是自定义的,但是1GB的内核空间是映射到同一块物理内存的,即内核空间是共享的。 更具体的Linux系统中进程的内存布局如下: :-: ![](https://img.kancloud.cn/2a/2d/2a2d0e8e69ef89465fe0a6057967b2bf_512x689.png) 以Java进程为例,JVM的堆结构其实是在这里的“堆”分配的一块空间,“堆外内存”也是在这里分配的,只是堆含义的主体对象不同罢了。   【参考】 《小林图解系统》