Linux进程地址空间
文章目录
- 1.程序地址空间与虚拟地址
- 2.虚拟地址是什么
- 3.虚拟地址空间结构体属性
- 4.为什么要有虚拟地址空间
- 5.一些问题
- 1.如何理解进程挂起?
- 2.堆是如何连续的呢?
1.程序地址空间与虚拟地址
我们在学习C/C++的时候学习到以下的内容:
那时候我们觉得我们访问地址是直接就是操作系统的地址码?
我们写一个代码来试一下:
我们发现,父子进程,输出地址是⼀致的,但是变量内容不⼀样
子进程和父进程在不发生更改的时候和父进程通过页表映射公用同一个内存空间
当子进程的内容发生更改的时候操作系统会重新分配一块新的内存来放子进程的数据
而我们用户在上层查看时仍然只能查看到虚拟地址空间所以我们观察到的地址是一样的
2.虚拟地址是什么
那么虚拟地址到底是什么?
其实虚拟地址空间就是操作系统给进程画的一张"大饼"
让进程以为自己可以独占所有的物理内存
但是由于进程过多,每个大饼又不一样,所以要将这些"大饼"管理起来
所以虚拟地址空间本质就是一个结构体(mm_struct)
3.虚拟地址空间结构体属性
虚拟地址主要目睹是管理区域划分,那我们如果管理一个数组的区域划分要定义怎样的结构体呢?
如上我们只需要定义一个结构体记录开始和结束即可
当我们需要对这个结构体进行调整的是,直接让start
/end
进行加减即可
那我们mm_struct
也是这样的
我们可以再次来理解代码和数据和虚拟地址的关系
- 现将进程加载到虚拟地址中,并且通过区域划分指定空间
- 加载程序申请物理空间
- 两只通过页表映射将物理地址转化为虚拟地址提交个用户使用
4.为什么要有虚拟地址空间
-
对于用户来说:物理地址通过页表映射产生的虚拟地址是连续的,将底层无序变为有序
-
用户使用虚拟地址去访问变量,需要现将虚拟地址转化为物理地址去找
当用户访问不合理(权限问题/野指针)的时候,操作系统可以直接杀掉进程来保护内存
如下面的情况
这个操作是通过页表的第三个内容"权限"来判定的
-
当用户访问的代码数据过大的时候
可以现将代码全部加载到虚拟空间(大饼)
在物理地址上只映射加载前面部分代码
当虚拟地址有而物理内存没有的时候,就会加载后续代码让程序继续运行这也叫缺页中断
-
让进程管理和内存管理解除耦合
5.一些问题
1.如何理解进程挂起?
查找页表找到对应的进程,将该进程的页表清空,将代码和数据换出,虚拟地址无需操作就可以将进程挂起
2.堆是如何连续的呢?
对的连续是在堆中加了一个指针将堆像链表一样连起来了,而且每个堆中有开始和结算的指针来控制对的开始和结束
不仅对如此其他的也是这样控制的: