Win32_Windows的内存管理

一 地址空间

  1 地址空间

    一个程序最大的寻址范围,对于Win32操作系统最大的寻址范围是2的32次方
      (0 - 0xFFFFFFFF).这个寻址范围由CPU决定。CPU的寻址范围越大程序难度降低。

  2 地址空间的划分
    2.1 用户空间
      地址范围 0 - 0x7FFFFFFF (2G),运行应用程序代码、数据等。
      2.2.1 空指针区(NULL区)
        地址范围 0 - 0x0000FFFF
      2.2.2 用户区
        地址范围 0x00010000 - 0x7FFEFFFF
      2.2.3 64K禁入区
        地址范围 0x7FFEFFFF - 0x7FFFFFFF
    2.2 内核空间
      地址范围 0x80000000 - 0xFFFFFFFF 被系统使用,运行驱动、内核的数据代码。
二 地址映射

  1 内存区域
    区域指一段连续的地址空间,区域的粒度和CPU的粒度、操作系统相关,目前通常都是以
      64K粒度存在。地址的对齐方式是以64K为边界
    区域的状态:
      1)保留 - 空闲的,可以被使用
      2)私有 - 已经被占有,但是还未使用
      3)映像 - 程序的代码使用
      4)映射 - 程序的数据使用

  2 物理内存
    实际可以使用的物理存储器

  3 虚拟内存
    使用硬盘空间作为内存扩展,也可以当作物理内存使用。

  4 内存页
    操作系统使用内存页的方式管理物理内存和虚拟内存,通常情况下内存页的大小为4K或者8K。
    每个内存页具有自己的状态,例如:只读/可写/可执行
  5 页目表
    用于管理内存页的表
    页目 - 页表  - 内存页
            - 内存页
       - 页表
         - 页表
    指针 31------22 21-------12 11------0
        页目    页表    偏移量

  6 地址空间的访问
    6.1 地址空间已经存在映射好的物理内存,直接使用,返回
    6.2 系统去虚拟内存中查找对应的内存页,如果未找到系统错误返回。
    6.3 系统将虚拟内存的内存页切换到物理当中。
    6.4 返回实际物理内存地址使用数据。

View Code
 1 #include "stdafx.h"
 2 #include "windows.h"
 3 
 4 void ShowSys()
 5 {
 6     SYSTEM_INFO info = {0};
 7     GetSystemInfo(&info);
 8     printf("内存页的大小:%d\n",info.dwPageSize);
 9     printf("可用最小地址:%p\n",info.lpMinimumApplicationAddress);
10     printf("可用最大地址:%p\n",info.lpMaximumApplicationAddress);
11     printf("区域的分配粒度:%d\n",info.dwAllocationGranularity);
12 }
13 
14 int main(int argc, char* argv[])
15 {
16 
17     ShowSys();
18     return 0;
19 }

  7 内存的使用
    7.1 虚拟内存
      适合对于大内存分配使用,一般情况下如果分配的内存大于1M
        应该使用虚拟内存分配方式
    7.2 堆内存
      适合对于小内存分配使用,一般情况下对于小于1M的内存分配使用。
        如:malloc/new
    7.3 堆栈内存
      系统维护的内存区

二 虚拟内存

  1 虚拟内存
    常用于大内存分配,分配的速度快,可以根据需要指定分配方式。

  2 虚拟内存的使用
    2.1 分配内存

LPVOID VirtualAlloc(
  LPVOID lpAddress,//NULL或者用于提交的内存地址
  DWORD dwSize,//分配的大小
  DWORD flAllocationType,//分配的方式
  DWORD flProtect);//内存访问方式

     分配最大空间小于用户区间(通常是2G)
    2.2 提交内存
      VirtualAlloc使用MEM_COMMIT方式,如:

pszBuf = (CHAR*)VirtualAlloc(
  pszBuf,//需要提交内存地址
  1024 * 1024 * 1024,MEM_COMMIT,PAGE_READWRITE);

    2.3 使用内存
    2.4 释放内存

BOOL VirtualFree(
LPVOID lpAddress,//释放的内存
DWORD dwSize,//释放的大小
DWORD dwFreeType);//释放的方式

  3 内存信息

VOID GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer);//获取内存信息
View Code
 1 #include "stdafx.h"
 2 #include "conio.h"
 3 #include "windows.h"
 4 
 5 void Status( )
 6 {    //获取内存信息
 7     MEMORYSTATUS status = { 0 };
 8     status.dwLength = sizeof( status );
 9     GlobalMemoryStatus( &status );
10     printf( "TotalPhys: %u\n",     status.dwTotalPhys );
11     printf( "AvailPhys: %u\n",     status.dwAvailPhys );
12     printf( "TotalPageFile: %u\n", status.dwTotalPageFile );
13     printf( "AvailPageFile: %u\n", status.dwAvailPageFile );
14     printf( "TotalVirtual: %u\n",  status.dwTotalVirtual );
15     printf( "AvailVirtual: %u\n",  status.dwAvailVirtual );
16     printf( "MemoryLoad: %d\n",    status.dwMemoryLoad );
17 }
18 
19 void Virtual( )
20 {    
21     Status( );
22     //地址分配
23     CHAR * pszBuf = (CHAR *)
24         VirtualAlloc( NULL, 
25         1024 * 1024 * 1024,
26         MEM_RESERVE,
27         PAGE_READWRITE );
28     printf( "MEM_RESERVE: %p\n", pszBuf );
29     
30     Status( );
31 
32     getch( );
33     //内存提交
34     pszBuf = (CHAR *)
35         VirtualAlloc( pszBuf,
36         1024 * 1024 * 1024,
37         MEM_COMMIT,
38         PAGE_READWRITE );
39     printf( "MEM_COMMIT: %p\n", pszBuf );
40     Status( );
41 
42     strcpy( pszBuf, "hello Virtual" );
43     printf( "%s\n", pszBuf );
44     
45     Status( );
46     getch( );
47 
48     //释放内存
49     VirtualFree( pszBuf, 
50         1024 * 1024 * 1024, 
51         MEM_RELEASE );
52 }
53 
54 int main(int argc, char* argv[])
55 {
56     Virtual( );
57     return 0;
58 }

三 堆内存

  1 堆内存的特点
    一般分配小数据内存,小于1M数据使用堆内存分配。
    一般程序执行后,会有一个默认堆,这个堆的大小一般为1M,一个程序可以有多个堆,
      通过堆内存管理器来管理堆中的内存。内存分配速度比VirtualAlloc慢

  2 堆内存的使用
    2.1 创建堆

HANDLE HeapCreate(
  DWORD flOptions,//创建标示
  DWORD dwInitialSize,//初始化大小
  DWORD dwMaximumSize);//最大大小

    2.2 分配内存

LPVOID HeapAlloc(
  HANDLE hHeap,//堆的句柄
  DWORD dwFlags,//分配标示
  DWORD dwBytes);//分配大小

   2.3 使用内存
   2.4 释放内存 

BOOL HeapFree(
  HANDLE hHeap,//堆的句柄
  DWORD dwFlags,//释放标示
  LPVOID lpMem);//释放的地址

   2.5 释放堆

BOOL HeapDestroy(HANDLE hHeap);//堆的句柄

  3 malloc/HeapAlloc/VirtualAlloc
    malloc内部调用 HeapAlloc
    HeapAlloc内部调用的 VirtualAlloc
    malloc分配内存:
    例如:100字节
    | 内存头 | 100字节 | 4字节尾部标示 |
    所使用 malloc分配的内存会使用这个内存头构成链表。

  4 堆的信息
    GetProcessHeap 当前进程默认堆的句柄
    GetProcessHeaps 当前进程所有堆的句柄

View Code
 1 #include "stdafx.h"
 2 #include "stdlib.h"
 3 #include "windows.h"
 4 
 5 void HeapInfo( )
 6 {    //默认堆的句柄
 7     HANDLE hHeap = GetProcessHeap();
 8     printf( "Default Heap: %p\n", hHeap );
 9     //所有的堆的句柄
10     HANDLE hHeaps[256] = { 0 };
11     DWORD nCount = 
12         GetProcessHeaps( 256, hHeaps );
13     printf( "All Heap: %d\n", nCount );
14     for( DWORD nIndex=0; nIndex<nCount; nIndex++ )
15     {
16         printf( "\t%d: %p\n", nIndex+1,
17             hHeaps[nIndex] );
18     }
19 }
20 
21 void Heap( )
22 {
23     HeapInfo( );
24 
25     //创建堆
26     HANDLE hHeap = HeapCreate( 
27         HEAP_GENERATE_EXCEPTIONS,
28         1024 * 1024, 0 );
29     printf( "HeapCreate: %p\n", hHeap );
30 
31     HeapInfo( );
32 
33     //内存分配
34     CHAR * pszBuf = ( CHAR * )
35         HeapAlloc( hHeap, HEAP_ZERO_MEMORY, 100 );  //分配后初始化为0
36     printf( "HeapAlloc: %p\n", pszBuf );
37 
38     strcpy( pszBuf, "hello Heap" );
39     printf( "%s\n", pszBuf );
40 
41     //内存释放
42     HeapFree( hHeap, 0, pszBuf );
43 
44     //释放堆
45     HeapDestroy( hHeap );
46 
47     HeapInfo( );
48 }
49 
50 int main(int argc, char* argv[])
51 {
52     CHAR * pszBuf = (CHAR *)malloc( 1024 );
53 
54     Heap( );
55     return 0;
56 } 

四 堆栈内存
  堆栈都是小数据的使用由系统维护,栈的大小一般在1M左右,
  例如:Windows下可以使用 _alloca 函数从栈上分配 内存,很少会用

五 内存映射文件

  1 内存映射文件
    可以将文件映射成内存,我们可以像使用内存一样使用文件。

  2 内存映射文件的使用
    2.1 创建或打开一个文件
      CreateFile
    2.2 创建内存映射文件

HANDLE CreateFileMapping(
  HANDLE hFile,//文件句柄
  LPSECURITY_ATTRIBUTES lpFileMappingAttributes,//安全属性
  DWORD flProtec,//保护模式
  DWORD dwMaximumSizeHigh,//大小的高32位
  DWORD dwMaximumSizeLow,//大小的低32位
  LPCTSTR lpName);//文件映射内核对象的名称

    2.3 映射成内存地址

LPVOID MapViewOfFile(
  HANDLE hFileMappingObject,//文件映射句柄
  DWORD dwDesiredAccess,//访问模式
  DWORD dwFileOffsetHigh,//地址偏移高32位
  DWORD dwFileOffsetLow,//地址偏移低32位
  DWORD dwNumberOfBytesToMap);//要映射的字节数

    2.4 使用内存
    2.5 制裁映射

BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);//卸载的地址

    2.6 关闭内存映射文件
      CloseHandle
    2.7 文件关闭
      CloseHandle

View Code
 1 #include "stdafx.h"
 2 #include "windows.h"
 3 
 4 void Map( )
 5 {    
 6     //创建文件
 7     HANDLE hFile = CreateFile( "C:\\map.dat",
 8         GENERIC_READ|GENERIC_WRITE,
 9         0, NULL, CREATE_ALWAYS,
10         FILE_ATTRIBUTE_NORMAL, NULL );
11     //创建文件映射
12     HANDLE hMap = CreateFileMapping( hFile, NULL,
13         PAGE_READWRITE, 0, 1024 * 1024, NULL );
14     //映射地址
15     CHAR * pszText = (CHAR *)MapViewOfFile( 
16         hMap, FILE_MAP_ALL_ACCESS,
17         0, 0, 1024 * 1024 );
18     //使用内存
19     strcpy( pszText, "Hello File Mapping" );
20     printf( "%s\n", pszText );
21     //卸载地址
22     UnmapViewOfFile( pszText );
23     //关闭文件映射
24     CloseHandle( hMap );
25     //关闭文件
26     CloseHandle( hFile );
27 }
28 
29 int main(int argc, char* argv[])
30 {
31     Map( );
32     return 0;
33 }  

 

 

posted @ 2012-10-17 17:25  吟唱黑暗  阅读(463)  评论(0编辑  收藏  举报