引入
这张图大家学习c/cpp的时候,应该都见过
有几个知识点在这里提一下。
- 先有命令行参数表,才有的环境变量表
- 这些表指向的内容和表,都在栈上面
- 未初始化和初始化数据会在进程运行期间,一直存在
- static变量会变成全局变量
进程地址空间定义
我们知道父进程和子进程在一开始是共享资源的(地址相同),当某个进程修改之后,才会创建新的资源。
但我们运行的结果显示:我们修改了变量但是,父进程和子进程的变量地址却是相同的。
这个修改后变量的地址叫虚拟地址
这里就引出了一个概念:我们之前所用到的所有地址,都是虚拟地址,这就是进程地址空间
文章最开始的那张图,就是进程地址空间(分为用户空间和内核空间),适用于很多语言。
原理
在进程地址空间中每个进程都有地址,父子进程是共用一个地址的。这些地址,在物理内存空间中,都有各自对应的地址。
当修改子进程的值的时候,进程空间的地址不会改变,但这个地址在物理空间中的映射就会改变。
这就解释了上面的现象
什么是进程地址空间
每个进程都有对应的地址空间,32位,0-4GB
操作系统对于每个进程都创建了一个地址空间,但对于大量的进程,操作系统需要对地址空间进行管理。
进程地址空间本质上就是数据结构
我们用**成对的整数来限制各个区域,**有以下作用
- 判断是否越界
- 可以扩大或缩小范围
如下所示
为什么要有进程地址空间以及页表
- 将物理内存变得有序,使得进程能够更好地管理
- 将进程管理和内存管理进行解耦合
- 有地址空间+页表,可以保护内存,防止非法访问
进程地址空间相关的一些问题
缺页中断:
我们malloc/new的时候,首先,在进程尝试访问其虚拟地址空间中的某个地址,但通过页表发现,该地址尚未映射到物理内存时。
操作系统就需要先将数据加载到物理内存中,从而继续执行进程。