虚拟内存和物理内存

rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml">

       在现代的操作系统中,当我们说到内存,往往需要分两部分来讲:物理内存和虚拟内存。从硬件上讲,虚拟空间是CPU内部的寻址空间,位于MMU之前,物理空间是总线上的寻址空间,是经过MMU转换之后的空间。

rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C02%5Cclip_filelist.xml">

       从逻辑上来讲,虚拟内存和物理内存之间存在着一对一、多对一的映射关系。一对一的关系很好理解,就是有一块物理内存,就有唯一的一块虚拟内存和它对应。但在CE中,这种情况是不存在的。我们知道,0x80000000—0xBFFFFFFF是对所有可用的内存和外设控制器的静态映射,其中低的一半地址是Cacheable的,高的一半地址是Uncacheable的。所谓静态映射,指这部分映射在系统启动时就已经创建了,和通常的动态创建相对应而言。因此,在CE中,每块内存至少映射了两次。

       静态映射的虚拟内存通常只供内核使用,应用程序和驱动如果也需要访问特定的内存(或者是IO,则需要重新分配一块虚拟内存,以映射到目标物理内存。这种情况下,常常使用VirtualAllocVirtualCopy

LPVOID VirtualAlloc(
  LPVOID lpAddress,
  SIZE_T dwSize,
  DWORD flAllocationType,
  DWORD flProtect
);

VirtualAlloc用于分配一片虚拟内存,参数lpAddress用于指定虚拟内存的地址。当lpAddress为空时,系统自动分配一个未用的虚拟地址。(有趣的是,在CE5中,如果lpAddress恰好是32MB(0x2000000)的倍数,则系统在以这个地址为基地址的进程中创建一块虚拟内存,一个后门哦:)如果我们只是需要任意一块内存,在flProtect参数中使用MEM_COMMIT来随即分配一片物理内存。反之,我们使用MEM_RESERVE参数,仅分配一块虚拟内存,然后使用VirtualCopy映射到目标物理内存。

BOOL VirtualCopy( 
  LPVOID lpvDest, 
  LPVOID lpvSrc, 
  DWORD cbSize, 
  DWORD fdwProtect 
);

VirtualCopy的源地址参数lpvSrc可以就是需要访问的物理地址,也可以是已经映射到目标物理地址的一个虚拟地址。目标地址参数lpvDest就是使用VirtualAlloc得到的虚拟内存。顾名思义,Copy以后,程序就可以在自己的进程空间里面访问目标内存了。

       除了上述的映射关系,其实还有两种特别的映射。

       一种是一对零,就是分配了虚拟内存,但是没有对应物理内存。在VirtualAlloc中使用MEM_RESERVEMEM_AUTOCOMMIT都会出现这种情况。前者是为了接下来使用VirtualCopy手动分配,后者则是一种延迟分配的策略,当读写操作发生时会自动分配。

       还有一种是零对一,就是一块物理内存,但是没有虚拟内存对应。那我们怎么访问呢?通常是DMA。比如某个控制器的FIFO寄存器,如果只需要DMA访问,就可以不映射虚拟内存。再比如从摄像头获得的图像,不经过CPU,直接显示在屏幕上,那么DMA的缓冲区也不需要映射虚拟地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值