一、程序地址空间
我们在学习C语言的时候,常用到如下的空间布局图:
内核空间 |
命令行参数环境变量 |
栈 |
共享区 |
堆 |
未初始化数据 |
初始化数据 |
正文代码 |
1.fork实验观察到的结论
我们在使用fork的时候,创建一个变量,在子进程中修改变量的值,但是不影响父进程打印原来的值,这是因为进程具有独立性,进程 = 内核数据结构+代码和数据,我们观察到&value的地址相同,所以该地址绝对不是物理地址。这叫做虚拟地址或者线性地址。 os必须负责将虚拟地址转换为物理地址
2.引入地址空间
比如,有一个富翁(os),有10亿美金(内存),给每个继承人(进程)都画了饼(进程空间地址),这个饼就是将来要继承的东西,此时这个饼需要被管理起来,以防富翁忘记采用先描述再组织的手段,struct mm_struct。
struct mm_struct{
long code_struct;
long code_start;
long code_end;
long init_start;
long init_end;
...
}
说明:
1.同一个变量,地址相同,其实是虚拟地址相同,内容不同是因为被映射到了不同的物理地址
2.为什么要存在地址空间? 假设没有地址空间,cpu调度进程,直接访问到物理内存,如果某个进程野指针越界访问到另一个进程,导致另一个进程出现问题。所以使用虚拟地址空间,是为了:1)防止地址被随意访问,保护物理内存和其他进程;2)将进程管理和内存管理进行解耦合;3)可以让进程以统一的视角,看待自己的代码和数据
3.malloc的本质
malloc需要向os申请内存,它在需要的时候再分配,这是因为os不允许任何的内存浪费或者不高效的行为,申请内存之后并不代表要立马使用,不使用的时候就是闲置状态。
4.重新理解地址空间
磁盘里保存代码和数据,进程开始,加载到内存,同时分配pcb,pcb分配虚拟地址,通过页表映射到物理内存,读取指令