操作系统需要完成抽象逻辑地址空间,保护独立地址空间,提供可以访问共享的内存空间,还需要根据程序运行场景虚拟出更多的地址空间这4步。
在操作系统中管理内存的方法包括:程序重定位、分段、分页、虚拟内存、按需分页虚拟内存等。
一、地址空间 和地址的生成
地址空间分为两种,一种是物理地址空间,它的地址空间和内存条代表的主存,硬盘代表的外村是直接映射的关系。第二种是逻辑地址空间,指的是应用程序所能看到的地址空间,它是一维的,由十六位数字表示。所有逻辑地址空间都会落实在一个物理地址空间上,这个映射规则由操作系统完成。
1)逻辑地址的生成
以Linux下的GCC的编译过程为例gcc的编译过程分为三步:
第一步将 文件1.c 文件2.c 文件3.c 分别通过编译器解析成汇编语言 文件1.s 文件2.s 文件3.s 。 可执行命令 gcc -S 文件1.s 文件2.s 文件3.s 只激活预处理,和编译
第二步将 文件1.s 文件2.s 文件3.s 分别通过汇编器 文件1.o 文件2.o 文件3.o 。 可执行命令 gcc -c 文件1.s 文件2.s 文件3.s 只激活预处理,和编译和汇编,生成obj目标代码文件
第三步将这些文件通过链接器生成 out 的可执行文件 如果不想编译出来成 a.out 名字 可执行命令 gcc -o 新文件名 待编译文件名
合成a.out 的文件过程中将文件头的数据大小,代码段,bss段,数据段 通过符号表中的引用信息来进行合并。
生成出来的a.out 文件包含四部分内容:
1) 文件头 : 包含了文件的加载信息和大小,其中
1.1) tsize = 代码段大小
1.2) dsize = 包含了初始化全局变量和初始化静态局部变量的数据段大小。
1.3) bsize =包含了未初始化的全局变量和未初始化的静态局部变量的bss段大小。
1.4) total_size =加载 a.out文件的总大小
2)代码段:包含了可执行代码
3)数据段: 包含了初始化全局变量和初始化静态数据
4)符号表: 可选,用于调式。
生成可执行文件后,通过一个loader方法将可执行文件上的段大小,偏移量映射到逻辑地址来进行正确的数据的访问和执行操作。
2)物理地址的生成
当CPU取到逻辑地址时,通过自身的MMU(内存管理单元),查询对应的物理地址 ,如果没有则到主存中去寻址。