进程地址空间
1.引言
1.1验证地址空间的内部布局
1.2.利用fork函数观察子进程对某个共享数据修改时父子进程读取到的值和地址
我们知道,子进程在创建的时候会和父进程共用一片代码和数据,当其中一个要修改其中的数据时会发生写时拷贝。
但是,根据我们看到的现象,发现子进程在修改了val 的值时,地址并未发生变化,Linux可以用一个变量表示不同的值,但是肯定不能,用一块地址存下两个值。
所以,我们得出结论:我们程序观察到的地址,不是物理意义上的地址,只是操作系统维护的虚拟地址也就是我们的地址进程空间。
我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理。
1.3页表和虚拟地址
进程地址空间中的地址,是维护出来让用户查看的,但是,他也一定需要和真正的物理地址联系起来,这靠什么?靠页表,让虚拟地址和物理地址对应起来,产生一对一的联系。
所以说,子进程和父进程的val值虚拟地址虽然相同,但是,由于页表上的对应关系不同,让他们指向了两个不同的物理地址,这样他们的值就产生了不同。
2.进程地址空间
2.1进程地址空间是怎么一回事
进程地址空间:没一个进程都会有一个进程地址空间大小[0.4GB](32位)
具体到代码部分就是,数据结构
2.2进程地址空间内部的属性(即空间区域划分)
地址空间划分的概念:进程地址空间是特定的数据结构,主要包含的字段是对地址空间进行区域划分,在特定位数的计算机中它能寻址的地址范围中划分为若干个区域,方便了操作系统的寻址操作。
这个区域划分,就向小时候在桌子上化三八线一样,[0,30]是你的,[30.100]是我的。
Linux的代码实现也就是跟什么差不多,进行区域划分。
区域划分目的:也就是为了方便管理,用特定的数字位进行划分,可以判断是否越位,是否需要扩容或者缩容。
区域划分的本质:也是为了,每一个地址都能被使用。
3.页表
3.1概念
页表:是用于支持虚拟内存管理的数据结构;主要用于存储虚拟地址到物理地址的映射关系;使得程序能够透明地使用虚拟地址空间,而无需管理物理内存(不必关心物理内存的具体布局)。
页表将虚拟地址转化为物理地址的过程,是由CPU内部的一个硬件组件MMU(内存管理单元)来完成的。MMU能够自动完成页表的映射、查找等工作,从而实现虚拟地址到物理地址的转化,进而找到数据并将其加载到CPU中进行处理。
CR3寄存器中保存了指向当前活动页表的物理地址,当MMU需要进行地址转化时,它会使用CR3中的值来定位正确的页表结构。
进程地址空间不具备对代码和数据的保存能力,而是通过页表机制和MMU的支持,将虚拟地址空间映射到物理内存,从而实现了代码和数据的保存和访问。
3.2关于malloc()函数和new()函数跟深层次的理解
在我们写程序的时候,使用malloc和new函数申请了空间,我们并不一定第一时间就去使用这份空间,但是呢,这份空间一直占据在哪里,让别人无法使用,自己又不用。操作系统是非常追求效率的,所以,面对这种情况,操作系统做了一些特殊处理。
一开始,用户申请空间的时候,为了防止物理内存空转,OS并不会分配物理空间,只会分配一块虚拟地址空间,然后这块虚拟地址空间在页表上是没有对应关系的。
那么什么时候分配物理空间呢?只有用户真正的要用到这个空间的时候,才分配。即用户要对这片空间进行写时拷贝的时候。 (延时分配效率)
这样就能够保证了OS的效率,防止内存空间的浪费。
用户在OS上使用malloc或者new函数要经过的几个步骤:
申请空间 -> 虚拟内存分配 -> 尝试写入 ->缺页中断 -> 物理内存的分配 -> 页表映射 -> 写入操作。
3.3 缺页中断
当用户尝试向虚拟地址进行写入,OS就会发现当前是往合理的空间内进行写入,且页表中当前并未建立虚拟地址到物理地址的映射关系,就会触发 “缺页中断”,将写入操作暂停,开辟物理内存,再建立对应的映射关系,一旦页表映射建立完成,用户就可以进行写入操作
3.4写时拷贝的原理
写时拷贝的过程:代码程序共享阶段 -> 尝试写入数据 -> 缺页中断 ->建立映射关系和分配物理地址-> 权限更新
页表上其实还有存储着权限位这个信息,当子进程创建的时候,继承父进程的数据和可执行程序时,父子进程在页表上记录着的,对于内存上的代码和数据都只有可读权限,当其中一方想要去修改数据时,发生写时拷贝的时候,就必然改动权限。
权限更新包括以下内容:
原页面权限:可读(保持不变)。这确保了其他进程不能通过这条路径改变数据,从而维护了数据的一致性。
新页面限:标记为可读写(rw),供请求写入的进程自由使用。
4.进程地址空间和页表存在的意义
4.1.将物理内存从无序变为有序,让进程以统一的视角,看待内存。
统一的视角:每个进程都有进程地址空间,这个空间是个连续的线性地址空间。意味着每个进程看到的内存布局时一样的,无论内存是如何分布,进程统一认为自己拥有一个完整的、连续的线性地址空间。
无序变为有序:通过进程地址空间和页表机制,即使物理内存是分散的,可以通过页表将它们映射成连续的虚拟地址空间。
4.2将进程管理和内存管理进行解耦合。
解耦合:页表的存在使得操作系统将进程管理和内存管理进行分离。进程管理模块主要负责创建、调度和终止进程,内存管理模块主要负责物理内存的申请和释放。通过页表,进程可以被加载到磁盘的任意位置,而不需要关心具体的内存布局。
4.3保护内存空间
内存保护:页表提供了内存保护机制,可以设置权限来控制不同内存区域的访问权限,如:有些区域只能特定的进程访问、有些区域只能读不能写等。
保护内存安全,对异常地址的访问时,它们就会拦住非法的请求操作。eg:访问野指针,程序崩溃,但并不影响OS正常的运行,也不影响其他进程正常运行,因为拦住你的是你自己的地址空间和页表,只会影响你自己。
- 点赞
- 收藏
- 关注作者
评论(0)