内存、虚拟内存的布局

       内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。计算机中所有程序的运行都是在内存中进行的,因此内存的性能对计算机的影响非常大。内存(Memory)也被称为内存储器,其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来,内存的是否稳定运行决定了计算机的稳定性。再引入虚拟内存之前我们再说说进程与程序的主要区别:

 (1)程序是永存的;进程是暂时的,是程序在数据集上的一次执行,有创建有撤销,存在是暂时的;

 (2)程序是静态的观念,进程是动态的观念;

 (3)进程具有并发性,而程序没有;

 (4)进程是竞争计算机资源的基本单位,程序不是。

 (5)进程和程序不是一一对应的: 一个程序可对应多个进程即多个进程可执行同一程序; 一个进程可以执行一个或几个程序

       我们平常说的每个进程都有自己独立的4G内存空间,但是实际上我们现在作用的个人计算机的内存水平最多也就是4G。那么问题来了,一个进程占据4G内存,一个程序往往分多个进程,首先是内存不够用,其次如果只这样的话,每个进程分开执行,这就存在执行等待的问题,甚至是进程阻塞。如此一来,计算机执行效率低下,显然不可取。由此,引入了虚拟内存,顾名思义,操作系统是给每个进程分配了4G的虚拟内存,而不是内存。也就是说程序运行时操作系统先将相关的文件和数据是先从磁盘上读取,通过地址映射到虚拟内存上,内存通过和虚拟内存和物理内存间的映射关系获取当下进程需要的文件和数据。

        Intel 80386 微处理器的诞生之前,计算机内存采用的是实地址模式,之后才是我们现在所用的保护地址模式。它是 Intel公司80286及以后的x86(80386,80486和80586等)兼容处理器(CPU)的一种操作模式。实模式被特殊定义为20位地址内存可访问空间上,它的容量是2的20次幂(1M)的可访问内存空间(物理内存和BIOS-ROM),软件可通过这些地址直接访问BIOS程序和外围硬件。实模式下处理器没有硬件级的内存保护概念和多道任务的工作模式。但是为了向下兼容,所以80286及以后的x86系列兼容处理器仍然是开机启动时工作在实模式下。1M 地址空间组成是由 16位的段地址和16位的段内偏移地址组成的。用公式表示为:物理地址=左移4位的段地址+偏移地址。286处理器体系结构引入了地址保护模式的概念,处理器能够对内存及一些其他外围设备做硬件级的保护设置(实质上就是屏蔽一些地址的访问)。Intel 80386使用之后保护模式才真正使用,它具有许多特性设计为提高系统的多道任务系统的稳定性。例如内存的保护分页机制硬件虚拟存储的支持。最终的物理计算公式为:物理地址 = 左移 4 位的段地址 + 偏移地址。保护模式下存在着分段地址映射,首先由基地址+逻辑地址/偏移量得到线性地址,当操所系统没有开启分页机制时,这个线性地址就是物理地址,若开启分页机制,得到的是虚拟地址,必须要经过分页地址映射才能得到我们想要的物理地址。

       在保护模式下,段是通过一系列被称之为 “ 描述符表 ” 的表所定义的。段寄存器存储的是指向这些表的指针。用于定义内存段的表有两种:全局描述符表 (GDT) 和局部描述符表 (LDT) 。GDT 是一个段描述符数组,其中包含所有应用程序都可以使用的基本描述符。在实模式中,段长是固定的 ( 为 64KB) ,而在保护模式中,段长是可变的,其最大可达 4GB 。LDT 也是段描述符的一个数组。与 GDT 不同, LDT 是一个段,其中存放的是局部的、不需要全局共享的段描述符。每一个操作系统都必须定义一个 GDT ,而每一个正在运行的任务都会有一个相应的 LDT 。

虚拟内存

接下来我们细说一下4G虚拟内存具体存放的是什么,我们所写的代码中的头文件,定义的变量他们归谁管。下面是我所画的虚拟内存的布局:

                                 

        虚拟内存的划分比例为3:1,用户可用的空间为3G,系统空间为1G。此图的地址是从上往下一次增大,顶部的128M是保留区空间,用户不能访问,访问系统就会报错。.txt段存放的是指令,.data段存放的是初始化过且不为0的全局变量和静态全局变量,.bss段存放的是未初始化的或者初始化为0的全局变量和静态全局变量(.bss段实际上是不存在的,系统采用预留的方式以节省空间,因为它的值为0,给它分配空间没有实际意义)。紧接着会预留一小部分空间放置越界访问,然后是堆栈分区,堆区地址由低地址向高地址分配(堆区(Heap)用于动态内存的开辟,需要注意的是动态内存的开辟并不是用户一次申请多少空间堆区就会减少多大空间,而是系统根据当前用户使用的实时空间进行分配,以免让开辟出来的空间处于空闲状态。),栈区(Stack)地址由高地址向低地址分配空间,在堆区和栈区之间是共享库的存储区域。在栈之后是程序的命令行参数和环境变量的存放区域。从0xc000 0000到0xFFFF FFFF的系统区域是直接内存访问区,常用部分区域和高端内存区域。

内存分配方式
(1) 从静态存储区域分配 。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量, static 变量 。
(2) 在栈上创建 。在执行函数时,函数内局部变量的存储单元都可以在栈上创建 ,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。
(3)从堆上分配 , 亦称动态内存分配 。程序在运行的时候用 malloc 或 new 申请任意多少的内存,程序员自己负责在何时用 free 或 delete 释放内存。

猜你喜欢

转载自blog.csdn.net/zhanxiao5287/article/details/83902332
今日推荐