引入
在学习C语言的时候,内存包括栈区、堆区、静态区
这个布局是内存吗? 不是!! 这是进程地址空间!
下面测试一下:
11540是bash进程
我们修改一下源程序,在观察下结果
发现父进程的g_value的值不变,这里得出一个结论:
子进程对全局数据修改,并不影响父进程
进程具有独立性 进程 = 内核数据结构+代码和数据
保证进程的独立性的方法是 写时拷贝
这里还有一个问题,就是我们可以发现子进程和父进程的地址是一样的,那么地址相同为什么变量的结果不同呢?
如果假设是物理地址,结果会不同吗? 答案肯定是不可能读取同一变量的地址,读到不同的数值!
所以这里的地址绝对不是物理地址
我们在语言层面用的地址,不是物理地址
我们称这种地址叫做虚拟地址or线性地址
我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理
OS必须负责将虚拟地址转化成物理地址 。
进程地址空间
故事1
故事2
小花VS小胖,两个小学生,闹了矛盾,最后在桌子上化了个线,画线的本质:区域划分!
区域划分:对线性区域进行1指定的start和end即可完成区域划分
两人相安无事了一阵子,过了一段时间,双方中的一方通过暴力扩张,已经占有整个桌面的70%甚至80%,该种行为我们称为扩大区域 ,修改start\end值即可。
所以之前说‘程序的地址空间‘是不准确的,准确的应该说成进程地址空间 ,那该如何理解呢?看图
上面的图就足矣说名问题,同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了 不同的物理地址!
fork在返回的时候,父子都有了,return两次,返回的本质就是写入、谁先返回,谁就让OS发生写实拷贝
扩展1 如果没有进程地址空间,os如何工作
如果没有进程地址空间,代码和数据存储在物理内存,那么会造成一些问题,如果寻址的地址出现越界,会影响到其他程序,无法保证进程的独立性。
为什么要有进程地址空间?
1 防止地址随意访问,保护物理内存与其他进程
2 将进程管理和内存管理进行解耦合
3 可以让进程以统一的视角,看待自己的代码和数据
扩展2 malloc本质
申请空间成功但是暂时不用,闲置状态,也会造成浪费
malloc先申请一个空间,假设我们在堆区上申请一个空间,即将堆区扩大,往上申请,然后将虚拟地址填入页表,但是物理地址暂时不填,同时也不在物理地址中申请空间,调用malloc就直接返回。采用缺页中断的方式