Linux--------进程地址空间
程序地址空间:
1. 研究背景
(1) kernel 2.6.32
(2) 32位平台
2. 程序地址空间
我们可以发现:输出的变量地址是一模一样的,可以理解为:因为子进程按照父进程为模板,父子并没有对变量进行任何修改。但若是将代码稍加改动:
我们发现,父子进程,输出的地址是一致的,但是变量的内容不一样。可以得出以下结论:
(1) 变量内容不一样,所以父子进程输出的变量内容绝对不是同一个变量
(2) 但是地址值是一样的,说明:该地址绝对不是物理地址
(3) 在Linux地址下,这种地址叫做虚拟地址
(4) 我们在C/C++语言中所看到的目的地址,全部都是虚拟地址。物理地址,用户一般看不到,有OS统一管理
OS必须负责将 虚拟地址 转化为 物理地址
进程地址空间
1. 早期内存管理机制
(1) 要运行一个程序,会把这些程序全部装入内存
(2) 当计算机同时运行多个程序时,必须保证这些程序用到的内存总量要小于计算机实际物理内存的大小问题
(3) 进程的地址空间不隔离。由于程序都是直接访问物理内存,所以恶意程序可以随意修改 别的进程的内存数据,以达到破坏的目的。
(4) 内存使用效率低。在A和B都运行的情况下,如果用户又运行了程序C,而程序C需要15M大小的内存才能运行,而此时系统只剩下4M的空间可供使用,所以此时系统必须在已运行的程序中选择一个将该程序的数据暂时拷贝到硬盘上,释放出部分空间供程序C使用,然后再将程序C的数据全部装入内存中运行
(5) 程序运行的地址不确定。当内存中的剩余空间可以满足程序C的要求后,操作系统就会在剩余空间中随机分配一段连续的20M大小的空间给程序C使用,因为是随机分配的,所以程序运行的地址是不确定的,这种情况下,程序的起始位置都是物理地址,而物理地址都是在加载之后才能确定。
2. 分段
(1) 在编写代码的时候,只要指明所属段,代码段和数据段中出现的所有的地址,都是从0开始,映射关系完全由操作系统维护
(2) CPU将内存分割成了不同的段,于是指令和数据的有效地址并不是真正的物理地址而是相对于段首地址的偏移地址。
解决问题:
(1) 因为段寄存器的存在,使得进程的地址空间得以隔离,越界问题很容易被判定出来
(2) 实际代码和数据中的地址,都是偏移量,所以第一条指令可以从0地址开始,系统会自动进行转化映射,也可以解决程序运行的地址不确定问题。
(3) 可是,分段并没有解决性能问题,在内存空间不足的情况下,依旧换入换出整个程序或整个段,无疑要造成内存和硬盘之间拷贝大量数据的情况,进而导致性能问题。
3. 分页 & 虚拟地址空间
上图足以说明:同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了不同的物理地址。