现在我急需一个内存管理的代码实例,有哪位高手可以提供一下,这里先谢谢了!我的信箱是[email protected].

解决方案 »

  1.   

    6.1 Win32下的内存管理介绍 在使用C语言是可以利用ANSI C的库函数alloc来分配或者用C++的new操作符来分配,内存但是对于一个操作系统来说利用系统提供的API函数来进行内存分配,这样可以更加有效的利用内存。 在Windows 3.X的时代,分配的内存可以有两种,全局的和局部的,例如GlobalAlloc和LocalAlloc。但在Win32的时代这些函数已经被废弃了,现在的内存只有一种就是虚存。在Win32中所有的进程所使用的内存区域是相互隔离的,每个进程都拥有自己的地址空间。而且系统使用了页面交换功能,就是利用磁盘空间来模拟RAM,在RAM中数据不使用时将会被交换到磁盘,在需要时将会被重新装入RAM。 在Win32中每个进程的地址空间为4GB,从0X00000000到0XFFFFFFFF。对于M$不同的操作系统来讲,应用程序可以使用地址空间是不同的。 Windows 9X 
    范围 作用 
    0X00000000 - 0X00000FFF MS DOS 
    0X00001000 - 0X003FFFFF 16位Windows 
    0X40000000 - 0X7FFFFFFF Win32应用程序 
    0X80000000 - 0XBFFFFFFF 内存映射文件,由Win32进程共享 
    0XC0000000 - 0XFFFFFFFF 操作系统 
    Windows NT/2000 
    范围 作用 
    0X00000000 - 0X7FFFFFFF Win32应用程序 
    0X80000000 - 0XFFFFFFFF 操作系统 
    Windows NT Server Enterprise Edition/Windows 2000 Advanced Server 
    范围 作用 
    0x00000000 - 0xBFFFFFFF Win32应用程序 
    0xC0000000 - 0XFFFFFFFF 操作系统 
    在系统中内存的最小单位是页,一页的大小不同,例如在Intel系统上Windows9X下一页的大小位4K,而在Alpha系统上NT下一页的大小为8K。通过GetSystemInfo函数可以获得系统信息: VOID GetSystemInfo(
      LPSYSTEM_INFO lpSystemInfo  // system information
    );
    typedef struct _SYSTEM_INFO { 
      union { 
        DWORD  dwOemId; 
        struct { 
          WORD wProcessorArchitecture; 
          WORD wReserved; 
        }; 
      }; 
      DWORD  dwPageSize; //页大小
      LPVOID lpMinimumApplicationAddress; //应用程序可以使用的最小地址
      LPVOID lpMaximumApplicationAddress; //应用程序可以使用的最大地址
      DWORD_PTR dwActiveProcessorMask; 
      DWORD dwNumberOfProcessors; //CPU数量
      DWORD dwProcessorType; //CPU类型
      DWORD dwAllocationGranularity; 
      WORD wProcessorLevel; 
      WORD wProcessorRevision; 
    } SYSTEM_INFO; 在Win32系统中内存页是可以设定保护方式(存取权限)的(例如可以设定某个内存页为只读,那么如果对这段内存进行写就会引发异常,而通过alloc或new分配的内存却不可以设置存取权限)。对内存的使用方式为先申请一段保留空间,然后提交这段内存空间并设置保护方式(申请和提交可以在一个步骤内完成),之后就可以对提交的内存区域进行操作,如果有必要可以改变内存的保护方式,在不在使用时回收内存,最后释放保留的内存空间。 对于很多关键性的应用来将自己管理内存的使用是很重要的,因为这样可以利用系统特性来提高应用性能和对内存的利用。对于桌面应用程序来说一般不需要直接使用系统提供的虚存管理API。 
    返回版权所有 闻怡洋 http://www.vchelp.net/
     
    6.2 虚存的使用 虚存的分配通过VirtualAlloc函数来完成,对于内存的分配和提交是以页为单位的,如果要求分配的内存大小不为页的整数倍,系统将会加大内存达到页的整数倍,而且会将申请的地址设定在页的边界,所以在申请时尽量按照页来进行申请。 LPVOID VirtualAlloc(
      LPVOID lpAddress,        // region to reserve or commit
      SIZE_T dwSize,           // size of region
      DWORD flAllocationType,  // type of allocation
      DWORD flProtect          // type of access protection
    );lpAddress 为申请的内存地址,在Win32中你可以自己指定申请内存的地址范围,如果为NULL则由系统分配一段空闲的地址 dwSize 内存大小,以字节为单位 flAllocationType 申请方式,可以取下面的值的组合: 
    MEM_RESERVE 要求系统保留申请的地址,如果申请成功,这段地址就无法再次被申请 
    MEM_COMMIT 提交已经申请的内存 
    MEM_TOP_DOWN 在由系统指定地址时要求系统从空闲区域的顶部开始分配,这样可以减少内存碎片 
    flProtect 指定内存的保护方式,可以选用下面的值: 
    PAGE_READONLY 只读 
    PAGE_READWRITE 读写 
    PAGE_EXECUTE 执行 
    PAGE_EXECUTE_READ 执行和读取 
    PAGE_EXECUTE_READWRITE 执行和读写 
    PAGE_NOACCESS 不允许任何存取 
    如果函数执行成功会返回要求的地址,否则将会返回NULL。 
    一段内存在申请后并不能马上使用,如果要使用必须先提交,并且在提交时指定内存的保护方式。对于未申请或已经申请但未提交的内存的任何操作都将会引发异常。 如果要释放或回收已经提交的内存可以使用VirtualFree: BOOL VirtualFree(
      LPVOID lpAddress,   // 地址
      SIZE_T dwSize,      // 大小
      DWORD dwFreeType    // 释放方式 
                          // MEM_DECOMMIT 回收已经提交的虚存 
                          //MEM_RELEASE 释放已经申请的虚存,dwSize这是必须为0
    );下面有一些例子可以帮助理解虚存的使用: //eg 1
    pMem = VirtualAlloc(NULL,1024*64*2,MEM_RESERVE,0); //申请128K虚存,地址由系统指定
    if(pMem) //假设返回值为 0X10000000
    {
    pMem2 =VirtualAlloc(pMem + 0X1000,1024*32,MEM_COMMIT,PAGE_READWRITE); //提交32K内存
    if(pMem2)// pMem2=0X10010000
    {
    memcpy(pMem2,p,32*1024);//对内存进行写
    memcpy(p2,pMem2,32*1024);//对内存进行读
    VirtualFree(pMem2,1024*32,MEM_DECOMMIT);//回收
    }
    VirtualFree(pMem,0,MEM_RELEASE);//释放
    }
    //eg 2
    pMem = VirtualAlloc((LPVOID)0X10000000,1024*64*2,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE); 
    //由0X10000000开始的128K虚存并同时提交该虚存,保护方式为可以读和写
    if(pMem) 
    {
    memcpy(pMem,p,32*1024);//对内存进行写
    memcpy(p2,pMem,32*1024);//对内存进行读
    VirtualFree(pMem,1024*64*2,MEM_DECOMMIT);//回收
    VirtualFree(pMem,0,MEM_RELEASE);//释放
    }//eg 3
    pMem = VirtualAlloc((LPVOID)0X10000000,1024*64*2,MEM_RESERVE | MEM_COMMIT,PAGE_READ); 
    //由0X10000000开始的128K虚存并同时提交该虚存,保护方式为只读
    if(pMem) 
    {
    memcpy(p2,pMem,32*1024);//对内存进行读
    memcpy(pMem,p,32*1024);//对内存进行写 引发异常,因为该段内存不允许写
    ...
    }在虚存被提交后可以修改虚存的保护方式,例如在你完成了数据写后可以将内存设置为只读,这样可以放置数据被错误的修改,函数为: BOOL VirtualProtect(
      LPVOID lpAddress,       // 地址
      SIZE_T dwSize,          // 大小
      DWORD flNewProtect,     // 新的保护方式
      PDWORD lpflOldProtect   // 旧的保护方式
    );你可以在使用虚存时先取得虚存的状态,函数为: DWORD VirtualQuery(
      LPCVOID lpAddress,                   // 地址
      PMEMORY_BASIC_INFORMATION lpBuffer,  // 返回的数据
      DWORD dwLength                       // 虚存大小
    );
    typedef struct _MEMORY_BASIC_INFORMATION {
        PVOID BaseAddress; // 查询的地址
        PVOID AllocationBase; // 分配的地址
        DWORD AllocationProtect; // 申请虚存时设定的保护方式
        SIZE_T RegionSize; // 虚存大小
        DWORD State; //当前状态
        //MEM_FREE 还为被申请
        //MEM_RESERVE 已经被申请,但未被提交
        //MEM_COMMIT 已经被提交
        DWORD Protect; // 提交虚存时设定的保护方式
        DWORD Type; // 
    } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; 本节提供一个例子来帮助大家理解虚存的使用,这个程序具有下面的界面:你可以点击按钮来执行指定功能,你可以试试看在会提交虚存时进行读写所引发的异常,和在设定为只读时对虚存进行写操作所引发的异常。 下载示范代码 此外对虚存可以进行加锁和解锁操作,经过加锁的虚存在不会被系统交换到磁盘上而始终被保存在RAM中。但加锁虚存可能会引起系统性能的下降,所以系统不允许同一进程加锁30页以上虚存,并且如果保护方式为PAGE_NOACCESS 的页。函数为: BOOL VirtualLock(
      LPVOID lpAddress,   // 地址
      SIZE_T dwSize       // 加锁的虚存大小,单位为字节
    );
    BOOL VirtualUnlock(
      LPVOID lpAddress,   // 地址
      SIZE_T dwSize       // 解锁的虚存大小,单位为字节
    );和虚存的分配和提交一样,加锁和解锁也是以页为单位的,即使你加锁2个字节也会引起对所在页的加锁。建议开发过程中如果没有非常的必要不要对虚存进行加锁。  
      

  2.   

    http://www.vchelp.net/vchelp/zteach/sam_sp_62.zip
      

  3.   

    要求编写一个包含两个线程的进程,一个线程从一个文件中读出要进行的内存操作,内存操作包括:
    时间:开始的执行时间。
    块数:分贝内存的粒度。
    操作:包括保留一个区域,提交一个区域,释放一个区域,回收一个区域,以及加锁和解锁一个区域,可以将这些操作编号,存放于文件中。
    大小:指块的大小。
    访问权限:共五种PAGE_READONLY PAGE_READWRITE PAGE_EXECUTE PAGE_EXECUTE_READ PAGE_EXECUTE_READWRITE。可以将这些权限编号,存放于文件中。
    另一个线程将页面大小、已使用的地址范围、物理内存总量以及虚拟内存等信息显示出来。
      

  4.   

    终于实现了!在这里要感谢大家的支持。特别是 Skt32(荒城之月) 给我提供的例子。如果有朋友需要我的例子的话说一声我上传过来!
      

  5.   

    我要,你传一个给我,谢谢。[email protected]
      

  6.   

     我的邮箱  [email protected]