在做uboot移植的时候对代码的重定向产生一个疑问,不理解为什么把uboot读到以链接地址作为起始地址的SDARM内存空间。对链接地址、虚拟地址、物理地址也傻傻分不清,后来学习计算机组成原理中的虚拟存储器时了解到虚地址(逻辑地址)、实地址(物理地址)以后我就认为链接地址就是虚拟地址。在学习了操作系统中存储器管理和虚拟存储器之后,我坚信我的猜测是正确的,只不过虚拟地址和物理地址的关系取决于存储管理的方式。
虚拟存储器:主存和辅存之外附加的硬件和软件的实现,也是用来提高辅存到主存的访问效率的一种机制。
虚拟地址:解决了程序员在编写程序时对内存空间安排使用的问题,也使程序员在编程时不必考虑地址空间的问题。虚拟地址应该可以有两个解释,对于计算机虚拟地址就是虚拟存储空间中地址,对于程序员虚拟地址就是编写程序时指定的地址。
链接地址:程序员在编写程序是使用的地址(严格的说是程序中存储指令的地址)。链接地址也是CPU运行地址,即CPU所能看到的地址,实际的物理地址需要mmu的转换。由于现在各种集成开发工具(IDE)的使用,让很多程序员(尤其是应用程序员)对链接地址感到很陌生。现在IDE会帮助我们完成所有的编译、链接工作。我认为链接地址可以从两个角度来看,从CPU的角度来看是运行地址,从程序员的角度来看链接地址也是虚拟地址的一部分。
我个人理解在虚拟地址概念引入后,在编写程序时所有地址都可以说是虚拟地址(逻辑地址),因为它们可以无限的大。指令地址也是数据,链接地址就是指出去哪个地址单元取出指令执行,CPU得到的始终时链接地址,然后转换得到实际指令的物理地址。
个人感觉虚拟地址、数据地址、链接地址的关系应该是这样的:
图1
单一连续分配,就是把用户程序读到和逻辑地址相同的物理地址,此时只能运行一个作业。单一连续分配需要程序员非常熟悉内存的分布。(逻辑地址、链接地址和物理地址相同)
动态可重定位分区分配,用于多道程序设计中,能够根据进程的实际需求动态的分配内存空间。(逻辑地址 != 物理地址)
分页存储管理方式,将程序划分为若干个大小固定的区域(页),也把物理内存划分为大小和页相等的块,通过页表完成页到块的映射。(逻辑地址!=物理地址)
分段是存储管理方式,把用户程序按照地址空间划分为不同的段,每段可以定义完整的信息。在存储分配时以段为单位,段的物理位置可以不同,从而实现了离散化分配。(逻辑地址!=物理地址)
段页式存储管理方式,同时具有前两者优点的存储管理方式。(逻辑地址!=物理地址)
逻辑地址和物理地址的关系由存储管理的方式有关。
uboot的重定位可以使用单一连续分配的方式来完成,因为uboot是上电后运行的第一个程序,它独占CPU。从Nand Flash读到SDARM的起始地址就是链接地址,此时虚拟地址和物理地址相同。
在做MMU验证实验时发现windows和ubuntu的打印结果不同,这个问题让我感到十分的困惑。
(1)windows下的代码:
图2
(2)windows下的结果
图3
(3) ubuntu下的代码
图4
(4)ubuntu下的结果
图5
由此可见在windows下同时运行的两个进程的变量地址相同,在ubuntu下同时运行的两个进程的结果不同。经过一番终于查询终于知道了其中的原因。现在的操作系统采用了栈空间随机化技术(ALSR),防止被黑客使用ret2libc攻击,然而这种技术需要软件和硬件的支持。我在windows下使用code::block编译的代码,生成的可执行文件没有支持这种技术,所以栈地址不变为且始终为a变量的虚拟地址。我使用Visual Studio 2015编译的代码就可以支持栈空间随机化技术(ALSR)。同样ubuntu也可以禁止栈空间随机化技术(ALSR)技术,禁止后两个进程的打印结果是相同的,如图6。
禁用(ALSR): sudo echo 0 > /proc/sys/kernel/randomize_va_space
启用(ALSR): sudo echo 2 > /proc/sys/kernel/randomize_va_space
图6
(1)虚拟存储,一个程序调入主存前在虚拟存储中进行分页,提高主存辅存的访问速度。
(2)现在操作系统中进程在内存中是离散化的分布。以分页存储管理方式来说,每个进程中有一个页表,记录着其在内存的位置。当CPU发出访问地址请求时,通过地址转换机构(MMU)来得到物理地址,然后通过存储管理器访问内存,实现数据的读写。
(3)如果访问主存时数据没有在主存中将产生缺页中断,这是需要把虚拟存储器中相应的页调入主存中。
图7
(1)数据执行保护,在内存上执行额外检查以帮助防止在系统上运行恶意代码,其基本原理是将数据所在内存页标识为不可执行。
《DEP原理及关闭》 http://blog.csdn.net/dongyewolong/article/details/8182055
(2)栈地址随机化ASLR技术。
《使用ret2libc攻击方法绕过数据执行保护》 http://blog.csdn.net/linyt/article/details/43643499
《栈随机化》 http://blog.csdn.net/swordmanwk/article/details/42044775