从操作系统角度了解进程虚拟地址空间

在看《程序员自我修养》的第一章时,较为详细的解释了为什么要使用进程虚拟地址空间这一方法,关于进程的虚拟地址空间可以查看我的这个博客:进程的虚拟地址空间,而书中也关联了一些操作系统的知识,随手一记。

一、简单内存分配策略

早期的计算机中程序是直接运行在物理内存上的,直接访问物理地址,例如:有两个进程,A程序需要占用10MB内存,B程序需要占用100MB的内存,而我们的内存是128MB,看起来貌似是没问题的,直接分配内存就可以,但这种分配内存方式存在很多问题:

1.地址空间不隔离

程序直接访问物理地址,他们之间没有“隔离墙”,所以很容易越界修改其他程序的数据,即使不是恶意程序,但其他程序也可能会有bug无意间修改,所以这是一个潜在的风险;

2.内存使用效率低

假设我们已经运行了几个程序,而此时某个程序正好占用物理地址的中间50MB,两端各多余39MB,而恰巧此时有一个新程序需要占用40MB的物理内存,由于进程占用内存需要连续,这就导致一个尴尬的状态,40MB的进程只能阻塞,或者经过很麻烦的一串操作来执行。内存使用效率极低;

3.程序运行地址不确定

程序每次需要装入运行时,需要分配一片足够大的内存区域,这个区域是不确定的,而程序在编写时其访问数据和指令跳转的目标地址很多都是固定的,这就导致了很多问题。
可以看到问题很多,所以我们引进中间层------虚拟地址来解决这个问题。

二、使用分段解决上述问题

分段的基本思路是将一段程序所需要内存空间通过虚拟内存空间一一映射到物理内存空间中,这种方法映射的大小和实际使用的大小是相同的。分段可以解决上述问题的第一个和第三个:

隔离程序

因为程序被映射到了不同的物理地址中,如果有程序访问的空间超出了他的特定范围,那么硬件就会判断这是一个非法的访问,直接拒绝并报告给操作系统或者监控程序。

运行地址确定

有了虚拟地址空间,则程序中的变量等访问的地址再虚拟地址空间中是确定的,所以也解决了第三个问题;

而内存使用效率的问题依旧没有得到解决,因为映射的大小依旧是原来大小,粒度还是比较大,所以人们想到了粒度更小的内存分割的情况------分页。

三、使用分页

分页的基本方法是把地址空间人为的分成固定大小的页,页的大小由硬件决定(一般是4K或者4M,但大多数选择4K),32位系统的虚拟地址空间共分为1 048 576个页,物理空间也是;将常用的数据和代码页装载到内存中,称作物理页,不常用的代码和数据保存到磁盘中,当使用时再读取到内存中,称作磁盘页,而虚拟内存中的页称作虚拟页;虚拟空间中有些页是被映射到同一个物理页中的,实现内存共享;
1.当进程需要使用不在内存中的页时,硬件捕获到此消息,称为页错误,然后操作系统接管进程将磁盘中的页装载到内存中,并建立映射关系;
2.保护也是页映射的目的,因为每个页可以设置权限属性,只有操作系统可以设置此属性。
3.虚拟存储需要借助MMU(Memory Manegement Unit)来进行页映射,CPU发出Virtual Address,经过MMU转换为Physical Address。

猜你喜欢

转载自blog.csdn.net/qq_45132647/article/details/105832404