windows内存

Windows内存地址空间

  1. 地址空间
    程序中可以寻址的最大范围。对于32位操作系统,
    地址空间范围为0-4G(2^32),地址空间越大,
    相对程序的编写就会容易。
  2. 地址空间的划分
    • 用户地址空间 0 - 2G(7FFFFFFF )
      存放用户的程序和数据。
      用户空间的代码是不能访问内核空间的数据和代码。
      • 空指针区(NULL区,0-64K)系统将地址小于64K指针,都认为是空指针。
      • 用户区
      • 64K禁入区(0x7FFEFFFF - 0x7FFFFFFF )
    • 内核地址空间 2G - 4G
      存放内核的代码和数据,例如系统驱动。
      内核空间代码是可以访问用户空间。

windows内存

  1. 区域
    区域就是连续的一块内存。区域的大小一般为64K或者64K倍数。每个区域都有自己的状态:

    • 空闲:没有被使用
    • 私有:被预定的区域
    • 映像:存放代码
    • 映射:存放数据
  2. 物理内存
    系统可以使用的实际内存。CPU可以直接访问的内存。

  3. 虚拟内存(硬盘交换文件)
    将硬盘文件虚拟成内存使用。(pagefile.sys 文件)
    CPU如果要访问虚拟内存数据,必须将虚拟内存数据
    放到物理内存。

  4. 内存页
    系统管理地址的最小单位。内存页大小为4K,每个
    内存页有自己的权限。

  5. 页目表
    指针地址
    31 22 21 12 11 0
    |-----------|------------|--------------|
    10位 10位 12位

     2^10=1024       1024           4K
      页目                  页表         页内偏移地址
    
  6. 从内存获取数据过程

    • 根据地址在物理内存中查找相应的位置。如果找到物理内存,取回数据。如果未找到,执行下一步.
    • 根据地址去虚拟内存中查找相应的位置。如果未找到,那么该地址没有内存空间,返回错误。如果找到,执行下一步.
    • 将该地址所在内存页,置换到物理内存中,同时将原物理内存数据,存入到虚拟内存中。
    • 将物理内存中的数据返回给使用者。
  7. 内存分配

    • 虚拟内存分配-适合大内存分配,一般是1M之上的内存。
    • 堆内存分配-适合小内存分配,一般是1M以下的内存。
      malloc/new
    • 栈内存分配-适合小内存分配,一般是1M以下的内存。

虚拟内存分配

  1. 虚拟内存分配
    速度快,大内存效率高。将内存和地址分配分别执行,可以在需要的时候再提交内存。常用字大型电子表格等处理。

  2. 虚拟内存使用

    • 内存分配
    	LPVOID VirtualAlloc(
    		LPVOID lpAddress,// NULL或提交地址
    		SIZE_T dwSize, //分配的大小
    		DWORD flAllocationType, //分配方式
    		DWORD flProtect //内存访问方式
    	);    分配成功返回地址
    
    • 分配方式:
      MEM_COMMIT - 提交内存,分配之后返回地址和内存空间
      MEM_RESERVE- 保留地址,分配之后只返回地址,内存空间不生成。要使用内存必须再次提交。
  • 使用
  • 释放
    BOOL VirtualFree(
    LPVOID lpAddress,//释放地址
    SIZE_T dwSize, //释放的大小0
    DWORD dwFreeType //释放方式
    );
    * 释放方式:
    MEM_DECOMMIT - 只释放内存,不释放地址
    MEM_RELEASE - 地址和内存都释放

堆内存 Heap

  1. 堆内存分配
    适合分配小内存,一般是小于1M的内存。一般每个程序都有自己的堆,默认大小为1M,会根据使用情况进行调整。

  2. 堆的使用

    • 堆的信息
      GetProcessHeap - 获得程序的第一个堆
      GetProcessHeaps - 获取程序中所有的堆
    • 创建堆
    		HANDLE HeapCreate(
    			DWORD flOptions,//创建选项
    			 SIZE_T dwInitialSize, //初始化大小1024*1024
    			 SIZE_T dwMaximumSize //最大值0
    		); 成功返回堆句柄
    
    • 从堆中分配内存(获取堆中内存的地址)
      LPVOID HeapAlloc(
      HANDLE hHeap, //堆句柄
      DWORD dwFlags, //分配方式
      SIZE_T dwBytes //分配大小210241024
      ); 成功返回地址

    • 使用内存

    • 释放内存
      BOOL HeapFree(
      HANDLE hHeap, // 堆句柄
      DWORD dwFlags, // 释放方式
      LPVOID lpMem // 释放地址
      );

    • 销毁堆
      BOOL HeapDestroy(
      HANDLE hHeap //堆句柄
      );
      当堆被销毁后,使用该堆分配内存全都被销毁。

  3. VirtualAlloc/HeapAlloc/malloc/new在Windows平台上,函数调用关系:
    new/malloc -> HeapAlloc。。。。。

栈内存

栈内存-每个线程都具有自己的栈,默认大小1M。
一般是系统维护栈。
Windows提供了 _alloca, 可以在栈上分配内存。

  • 内存映射文件
    将文件映射成内存来使用。当使用内存时,就是在使用文件。
    内存映射文件的使用
    1. 创建或打开文件CreateFile
    2. 创建内存映射文件
    HANDLE CreateFileMapping(
    	HANDLE hFile, //文件句柄
    	LPSECURITY_ATTRIBUTES lpAttributes, //安全属性
    	DWORD flProtect,//访问方式
    	DWORD dwMaximumSizeHigh,//内存映射文件大小的高32
    	DWORD dwMaximumSizeLow, //内存映射文件大小的低32
    	 LPCTSTR lpName //命名,可以为NULL
    );    创建成功返回句柄
    

	3. 获取内存映射文件某个地址
	```
	LPVOID MapViewOfFile(
		HANDLE hFileMappingObject,//内存映射文件句柄
		DWORD dwDesiredAccess,       //访问模式
		DWORD dwFileOffsetHigh,  //偏移量的高32位
		DWORD dwFileOffsetLow,       //偏移量的低32位
		SIZE_T dwNumberOfBytesToMap  //不使用
		 //映射的字节数量
	); 成功返回地址
	```
		dwFileOffsetHigh和dwFileOffsetLow合成的偏移量,必须是区域粒度的整数倍(64K的整数倍)


4. 使用内存
5. 将 地址 和 内存映射文件的 某个部分分开
	BOOL UnmapViewOfFile(
		LPCVOID lpBaseAddress //卸载地址
	);
6. 关闭内存映射文件
	CloseHandle – 一旦关闭,就没了
7. 关闭文件
	CloseHandle
posted @ 2016-11-07 20:24  呉语伦比  阅读(404)  评论(0)    收藏  举报