MEMORY_BASIC_INFORMATION中 BaseAddress 和 AllocationBase 区别

地址空间在运行中映射为实际的物理页面。
 
·        区域
区域指的是上述地址空间中的一片连续地址。区域的大小必须是粒度(64k) 的整数倍,不是的话系统自动处理成整数倍。不同CPU粒度大小是不一样的,大部分都是64K。
区域的状态有:空闲、私有、映射、映像。
在你的应用程序中,申请空间的过程称作保留(预订),可以用VirtualAlloc;删除空间的过程为释放,可以用VirtualFree。
        在程序里预订了地址空间以后,你还不可以存取数据,因为你还没有付钱,没有真实的RAM和它关联。
这时候的区域状态是私有;
默认情况下,区域状态是空闲;
当exe或DLL文件被映射进了进程空间后,区域状态变成映像;
当一般数据文件被映射进了进程空间后,区域状态变成映射。
 
·        物理存储器
Windows各系列支持的内存上限是不一样的,从2G到64G不等。理论上32位CPU,硬件上只能支持4G内存的寻址;能支持超过4G的内存只能靠其他技术来弥补。顺便提一下,Windows个人版只能支持最大2G内存,Intel使用Address Windows Extension (AWE) 技术使得寻址范围为236=64G。当然,也得操作系统配合。
        内存分配的最小单位是4K或8K,一般来说,根据CPU不同而不同,后面你可以看到可以通过系统函数得到区域粒度和页面粒度。
 
·        页文件
页文件是存在硬盘上的系统文件,它的大小可以在系统属性里面设置,它相当于物理内存,所以称为虚拟内存。事实上,它的大小是影响系统快慢的关键所在,如果物理内存不多的情况下。
       每页的大小和上述所说内存分配的最小单位是一样的,通常是4K或8K。
 
映射过程
进程地址空间的地址是虚拟地址,也就是说,当取到指令时,需要把虚拟地址转化为物理地址才能够存取数据。这个工作通过页目和页表进行。
 
页目大小为4K,其中每一项(32位)保存一个页表的物理地址;每个页表大小为4K,其中每一项(32位)保存一个物理页的物理地址,一共有1024个页表。利用这4K+4K*1K=4.4M的空间可以表示进程的1024*1024* (一页4K) =4G的地址空间。
高10位用来找到1024个页目项中的一项,取出页表的物理地址后,利用中10位来得到页表项的值,根据这个值得到物理页的地址,由于一页有4K大小,利用低12位得到单元地址,这样就可以访问这个内存单元了。
        每个进程都有自己的一个页目和页表,那么,刚开始进程是怎么找到页目所在的物理页呢?答案是CPU的CR3寄存器会保存当前进程的页目物理地址。
        当进程被创建时,同时需要创建页目和页表,一共需要4.4M。在进程的空间中,0xC030 0000~0xC030 0FFF是用来保存页目的4k空间。0xC000 0000~0xC03F FFFF是用来保存页表的4M空间。也就是说程序里面访问这些地址你是可以读取页目和页表的具体值的(要工作在内核方式下)。有一点我不明白的是,页表的空间包含了页目的空间!
        至于说,页目和页表是保存在物理内存还是页文件中,我觉得,页目比较常用,应该在物理内存的概率大点,页表需要时再从页文件导入物理内存中。
        页目项和页表项是一个32位的值,当页目项第0位为1时,表明页表已经在物理内存中;当页表项第0位为1时,表明访问的数据已经在内存中。还有很多数据是否已经被改变,是否可读写等标志。另外,当页目项第7位为1时,表明这是一个4M的页面,这值已经是物理页地址,用虚拟地址的低22位作为偏移量。还有很多:数据是否已经被改变、是否可读写等标志。
 



MEMORY_BASIC_INFORMATION这个结构中的两个成员的区别:

  1. typedef struct _MEMORY_BASIC_INFORMATION {    
  2. PVOID BaseAddress;    
  3. PVOID AllocationBase;    
  4. DWORD AllocationProtect;    
  5. SIZE_T RegionSize;    
  6. DWORD State;    
  7. DWORD Protect;    
  8. DWORD Type;  
  9. } MEMORY_BASIC_INFORMATION,  *PMEMORY_BASIC_INFORMATION;   

  1. <strong>以下引用csdn论坛的观点,我认为这解释地比较清楚了:</strong>  
  2. PVOID BaseAddress;  //该页的基地址,是VirtualQuery(Ex)第一个参数下舍入下一个页面的边界的值  
页的边界启始地址. 在地址形式上类似: 0xXXXXX000(X86,页大小为4KB)

  1. PVOID AllocationBase;  

在进程中为了使用内存,必须保留(Reserved)内存和占有内存(Committed) -使用VirtualAlloc()函数. VirtualAlloc分配的内存称为区域(Region)- 一片连续的页. 为了分配效率(?) Windows会以64-KB为边界计算区域的启始地址,所以区域的启始地址在形式上类似: 0xXXXX0000,这里的64KB页就是所谓的分配粒度,因此 AllocationBase正是一个区域(Region)的启始地址


另外,BaseAddress一定在AllocationBase地址范围之内
(The page pointed to by the BaseAddress member is contained within this allocation range)
以下是我在应用VirtualQuery函数时MEMORY_BASIC_INFORMATION结构里面的
PVOID BaseAddress;
PVOID AllocationBase;两个成员的返回值

=================================
BaseAddress   AllocationBase
0x00401000    0x00400000
0x00401700    0x00400000
0x00401800    0x00400000
0x00401a00    0x00400000

=================================

BaseAddress - the address of the queried memory page ( VirtualQuery(LPCVOID lpAddress,... ).

AllocationBase - the beginning of the allocated memory block. It is used for deallocation. BaseAddress >= AllocationBase.

If you are querying stack then AllocationBase will be the lowest address of the stack (the stack top)
发布了18 篇原创文章 · 获赞 2 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章