WINDOWS内存管理方式综述

 

WINDOWS内存管理方式主要分为:段式管理、页式管理、段页式管理。
  页式管理:页式管理的基本原理将各进程的虚拟空间划分成若干个长度相等的页(page),页式管理把内存空间按页的大小划分成片或者页面(page frame),然后把页式虚拟地址与内存地址建立一一对应页表,并用相应的硬件地址变换机构,来解决离散地址变换问题。页式管理采用请求调页或预调页技术实现了内外存存储器的统一管理。 其优点是没有外碎片,每个内碎片不超过页大小(空间浪费小)。一个程序不必连续存放。便于改变程序占用空间的大小(主要指随着程序运行而动态生成的数据增多,要求地址空间相应增长,通常由系统调用完成而不是操作系统自动完成)。 缺点程序全部装入内存,要求有相应的硬件支持。例如地址变换机构,缺页中断的产生和选择淘汰页面等都要求有相应的硬件支持。这增加了机器成本。增加了系统开销,例如缺页中断处理机,请求调页的算法如选择不当,有可能产生抖动现象。 虽然消除了碎片,但每个作业或进程的最后一页内总有一部分空间得不到利用,如果页面较大,则这一部分的损失仍然较大。 
  段式管理:基本思想就是把程序按内容或过程(函数)关系分成段,每段有自己的名字。一个用户作业或进程所包含的段对应一个二维线形虚拟空间,也就是一个二维虚拟存储器。段式管理程序以段为单位分配内存,然后通过地址影射机构把段式虚拟地址转换为实际内存物理地址。 程序通过分段(segmentation)划分为多个模块,如代码段、数据段、共享段。其优点是:可以分别编写和编译。 可以针对不同类型的段采取不同的保护(存储保护容易)。 可以按段为单位来进行共享(存储共享容易),包括通过动态链接进行代码共享(能动态连接)。 
  段页式管理:为了实现段页式管理,系统必须为每个作业或进程建立一张段表以管理内存分配与释放、缺段处理、存储保护及地址变换等。另外,由于一个段又被划分成了若干页,每个段又必须建立一张页表以把段中的虚页变换成内存中的实际页面。显然,与页式管理时相同,页表中也要有相应的实现缺页中断处理和页面保护等功能的表项。另外,由于在段页式管理中,页表不再是属于进程而是属于某个段,因此,段表中应有专项指出该段所对应页表的页表始址和页表长度。 因为段页式管理是段式管理的页式管理方案结合而成的,所以具有它们二者的优点。但反过来说,由于管理软件的增加,复杂性和开销也就随之增加了。另外,需要的硬件以及占用的内存也有所增加。更重要的是,如果不采用联想寄存器的方式提高CPU的访内速度,将会使得执行速度大大下降。
API函数

1.使用全局和局部函数分配和释放内存的API函数

/* 头文件 */

#include <windows.h>

#include <stdio.h>

*************************************

* int main(void)

* 功能  演示Global*函数的使用

* 参数  无

**************************************/

int main(void)

{  

     LPVOID lpMem;     //内存地址

     HGLOBAL hMem;  //内存句柄

     SIZE_T sizeMem;   //内存大小

     UINT uFlags; //属性

     //分配内存

     lpMem = (LPVOID)GlobalAlloc(GPTR,1000);

     //将数据复制到内存中

     lstrcpy(lpMem,"this is a string");  

     //获得内存属性,打印

     uFlags = GlobalFlags(lpMem);

     printf("内存中的内容:\"%s\",内存地址:0x%.8x,内存属性:%u\n",

          lpMem,lpMem,uFlags);

     //释放

     GlobalFree(lpMem);

     //分配内存,获取信息

     hMem = GlobalAlloc(GMEM_MOVEABLE,1000);

     sizeMem = GlobalSize(hMem);

     uFlags = GlobalFlags(hMem);

     //打印信息

     printf("内存大小:%d,内存句柄:0x%.8x,内存属性:%u\n",

          sizeMem,hMem,uFlags);

     //锁定

     lpMem = GlobalLock(hMem);

     //释放

     GlobalFree(hMem);

     return 0;

}

2.分配和释放可读可写的虚拟内存页面

/* 头文件 */

#include <windows.h>

#include <stdio.h>

/*************************************

* int main(void)

* 功能  演示虚拟内存的使用

* 参数  未使用

**************************************/

int main(void)

{  

     SIZE_T sizeVirtual = 4000;       //大小

     LPVOID lpRound = (LPVOID)0x100000FF;   //地址

     MEMORY_BASIC_INFORMATION  mbi;   //内存信息

     //分配内存,直接分配已提交的内存

     LPVOID lpAddress = VirtualAlloc(

          lpRound,sizeVirtual,

          MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE

          );

     if(lpAddress == NULL)

     {

          printf("VirtualAlloc error: %d\n",GetLastError());

          return 1;

     }

     printf("Alloc:MEM_COMMIT|MEM_RESERVE\n");

     //复制数据到内存中

     CopyMemory(lpAddress,"hello",lstrlen("hello"));

     printf("分配、复制成功,地址:0x%.8x,内容:%s\n",

          lpAddress,lpAddress);

     //获取内存信息并打印

     VirtualQuery(lpAddress,&mbi,sizeof(mbi));

     printf("使用VirtualQuery获得的信息:\n"

          "BaseAddress:0x%.8x\tAllocationBase:0x%.8x\t"

          "AllocationProtect:0x%.8x\tRegionSize:%u\t"

          "State:0x%.8x\tProtect:0x%.8x\tType:0x%.8x\n",

          mbi.BaseAddress,mbi.AllocationBase,

          mbi.AllocationProtect,mbi.RegionSize,

          mbi.State,mbi.Protect,mbi.Type

          );

     ////设置为READ-ONLY属性

     //if(!VirtualProtect(lpAddress,0,PAGE_READONLY,NULL))

     //{

     //  printf("VirtualProtect error: %d",GetLastError());

     //  return 1;

     //}

     ////测试READ-ONLY属性,异常

     //CopyMemory(lpAddress,"read only",lstrlen("read only"));

     //printf(lpAddress);

     ////获取内存信息并打印

     //VirtualQuery(lpAddress,&mbi,sizeof(mbi));

     //printf("使用VirtualQuery获得的信息:\n"

     //  "BaseAddress:0x%.8x\tAllocationBase:0x%.8x\t"

     //  "AllocationProtect:0x%.8x\tRegionSize:%d\t"

     //  "State:0x%.8x\tProtect:0x%.8x\tType:0x%.8x\n",

     //  mbi.BaseAddress,mbi.AllocationBase,

     //  mbi.AllocationProtect,mbi.RegionSize,

     //  mbi.State,mbi.Protect,mbi.Type

     //  );

     //DECOMMIT释放,页面将变为保留状态

     printf("Free: DECOMMIT\n");

     if(!VirtualFree(lpRound,sizeVirtual,MEM_DECOMMIT))

     {

          printf("VirtualFree error: %d",GetLastError());

          return 1;

     }

     //获取内存信息并打印

     VirtualQuery(lpAddress,&mbi,sizeof(mbi));

     printf("使用VirtualQuery获得的信息:\n"

          "BaseAddress:0x%.8x\tAllocationBase:0x%.8x\t"

          "AllocationProtect:0x%.8x\tRegionSize:%u\t"

          "State:0x%.8x\tProtect:0x%.8x\tType:0x%.8x\n",

          mbi.BaseAddress,mbi.AllocationBase,

          mbi.AllocationProtect,mbi.RegionSize,

          mbi.State,mbi.Protect,mbi.Type

          );

     //释放内存

     printf("Free:RELEASE\n");

     if(!VirtualFree(lpAddress,0,MEM_RELEASE))

     {

          printf("VirtualFree error: %d",GetLastError());

          return 1;

     }

     return 0;

}

原文地址:https://www.cnblogs.com/mangci/p/3016357.html