获取WinCE进程的内存信息

 

//=====================================================================
//TITLE:
//    获取WinCE进程的内存信息
//AUTHOR:
//    norains
//DATE:
//    Wednesday 3- February-2010
//Environment:
//     WINDOWS CE 5.0
//=====================================================================


    获取WinCE下的进程的内存信息并不困难,完全可以借助微软自带的Remote工具,比如:Remote Process Viewer,Remote Heap Walker等等。如果是日常的调试,不做别的特殊用途,那么这些完全够用了。但如果你不满足于此,而是非常渴望知道如何在自己的程序也能获取系统的进程相关信息,那么你可以继续往下阅读。:)

 

    首先我们需要做的是,先获取当前活动的进程。因为我们无法保证每次的进程数目都是相同的,所以为了简便,我们直接将STL的vector作为缓存进行数据的保存。

 

    故,我们的函数会如下:

  1. BOOL GetAllProcInfo(std::vector<PROCESSENTRY32> &vtProcInfo)  
  2. {    
  3.  vtProcInfo.clear();  
  4.  return EnumProcInfo(EnumAllProcessProc,&vtProcInfo);  
  5. }  

 

    该函数并没有做任何实质的事情,只是将保存的缓存清空,然后再调用EnumProcInfo函数。

 

    EnumProcInfo函数用来枚举系统中的进程信息,其实现如下:

  1. BOOL EnumProcInfo(PROC_EMUN_PROC pProcFunc,VOID *pParam)  
  2. {  
  3.  BOOL bRes = FALSE;  
  4.  HANDLE hSnapshot = INVALID_HANDLE_VALUE;  
  5.   
  6.  static const DWORD TH32CS_SNAPNOHEAPS = 0x40000000;  
  7.   
  8.  __try  
  9.  {      
  10.   if(pProcFunc == NULL)  
  11.   {  
  12.    __leave;  
  13.   }  
  14.   
  15.   hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPNOHEAPS, 0);  
  16.   if (hSnapshot == INVALID_HANDLE_VALUE)  
  17.   {  
  18.    __leave;  
  19.   }  
  20.     
  21.   PROCESSENTRY32 processEntry;  
  22.   processEntry.dwSize = sizeof(PROCESSENTRY32);  
  23.   
  24.   if(Process32First(hSnapshot, &processEntry) == FALSE)  
  25.   {  
  26.    __leave;  
  27.   }  
  28.   
  29.   if((*pProcFunc)(processEntry,pParam) == FALSE)  
  30.   {  
  31.    bRes = TRUE;  
  32.    __leave;  
  33.   }  
  34.   
  35.   while (Process32Next(hSnapshot, &processEntry) != FALSE)  
  36.   {  
  37.    if((*pProcFunc)(processEntry,pParam) == FALSE)  
  38.    {  
  39.     break;  
  40.    }  
  41.      
  42.   }  
  43.     
  44.   bRes = TRUE;  
  45.  }  
  46.  __finally   
  47.  {  
  48.   if (hSnapshot != INVALID_HANDLE_VALUE)  
  49.   {  
  50.    CloseToolhelp32Snapshot(hSnapshot);  
  51.    hSnapshot = NULL;  
  52.   }  
  53.  }  
  54.   
  55.  return bRes;  
  56. }  

    看起来很复杂,其实原理很简单。

 

    首先我们看一下其形参,pProcFunc保存的是回调函数地址,当搜索到系统的进程时,会调用该地址指向的函数,然后再将pParam形参传递过去。

 

    了解形参之后,我们再往下看。

 

    CreateToolhelp32Snapshot用来创建一个搜索快照的句柄,我们根据此句柄来获取系统当前的进程信息。和微软的其它枚举函数类似,第一次查找调用的是XXXFirst,接下来就是就是XXXNext。

 

    这样,通过GetAllProcInfo就能获取系统当前的进程信息。

 

    获得了当前进程信息,我们可以干的事情就多了。那么,我们接下来先做点什么呢?我们就先获取一下HeapList吧。

 

    为了方便,我们也定义了一个函数,用来获取HeapList:

  1. BOOL GetHeapList(DWORD dwProcID,std::vector<HEAPLIST32> &vtHeapList)  
  2. {  
  3.  BOOL bRes = FALSE;  
  4.  HANDLE hSnapShot = INVALID_HANDLE_VALUE;  
  5.   
  6.  __try  
  7.  {  
  8.   vtHeapList.clear();  
  9.   
  10.   hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, dwProcID);  
  11.   if(hSnapShot == INVALID_HANDLE_VALUE)  
  12.   {  
  13.    __leave;  
  14.   }  
  15.   
  16.   HEAPLIST32 heapList;  
  17.   heapList.dwSize = sizeof(HEAPLIST32);  
  18.   
  19.   //Begin to find the heap list   
  20.   if(Heap32ListFirst(hSnapShot,&heapList) == FALSE)  
  21.   {  
  22.    __leave;  
  23.   }  
  24.   vtHeapList.push_back(heapList);  
  25.   
  26.   while(Heap32ListNext(hSnapShot, &heapList) != FALSE)  
  27.   {  
  28.    vtHeapList.push_back(heapList);  
  29.   }  
  30.   
  31.   bRes = TRUE;  
  32.  }  
  33.  __finally  
  34.  {  
  35.   if(hSnapShot != INVALID_HANDLE_VALUE)  
  36.   {  
  37.    CloseToolhelp32Snapshot(hSnapShot);  
  38.   }  
  39.  }  
  40.   
  41.  return bRes;  
  42. }  

 

    结构和思维其实和列举进程信息的相同,在此不再赘述。不过这里唯一需要提一下的是该函数的形参:dwProcID。

 

    可能大家无法从GetAllProcInfo看出和dwProcID有什么联系,其实GetAllProcInfo函数返回的数值中,有个th32ProcessID就是和此相关。

 

    如果用代码标示,我们可以这样书写:

  1. std::vector<PROCESSENTRY32> vtProcInfo;  
  2. GetAllProcInfo(vtProcInfo);  
  3. std::vector<HEAPLIST32> vtHeapList;  
  4. GetHeapList(vtProcInfo[0].th32ProcessID,vtHeapList);  


    既然能获得了HeapList,我们就再接再厉,来获取HeapEntry信息:

  1. BOOLGetHeapEntry(DWORD dwProcID,const HEAPLIST32 &heapList,std::vector<HEAPENTRY32> &vtHeapEntry)  
  2. {  
  3.  BOOL bRes = FALSE;  
  4.  HANDLE hSnapShot = INVALID_HANDLE_VALUE;  
  5.   
  6.  __try  
  7.  {  
  8.   vtHeapEntry.clear();  
  9.   
  10.   hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, dwProcID);  
  11.   if(hSnapShot == INVALID_HANDLE_VALUE)  
  12.   {  
  13.    __leave;  
  14.   }  
  15.   
  16.   HEAPENTRY32 heapEntry = {0};  
  17.   heapEntry.dwSize = sizeof(HEAPENTRY32);  
  18.   
  19.   //Begin to find the heap entry     
  20.   if(Heap32First(hSnapShot, &heapEntry, heapList.th32ProcessID, heapList.th32HeapID) == FALSE)  
  21.   {  
  22.    __leave;  
  23.   }  
  24.   vtHeapEntry.push_back(heapEntry);  
  25.   
  26.   while(Heap32Next(hSnapShot, &heapEntry) != FALSE)  
  27.   {  
  28.    vtHeapEntry.push_back(heapEntry);  
  29.   }  
  30.   
  31.   bRes = TRUE;  
  32.  }  
  33.  __finally  
  34.  {    
  35.   if(hSnapShot != INVALID_HANDLE_VALUE)  
  36.   {  
  37.    CloseToolhelp32Snapshot(hSnapShot);  
  38.   }  
  39.  }  
  40.   
  41.   
  42.  return bRes;  
  43. }  
  44.   
  45.    

    获取HeapEntry信息后,我们还可以做一件事情,就是统计Heap的大小。我们也可以将其作为一个函数:

  1. DWORD GetHeapSize(const std::vector<HEAPENTRY32> &vtHeapEntry)  
  2. {  
  3.  DWORD dwSize = 0;  
  4.  for(std::vector<HEAPENTRY32>::const_iterator iter = vtHeapEntry.begin(); iter != vtHeapEntry.end(); ++ iter)  
  5.  {  
  6.   dwSize += iter->dwBlockSize;  
  7.  }  
  8.   
  9.  return dwSize;  
  10. }  

 

    基本上,关于Heap的信息,我们先暂时讨论到这里。接下来,我们来根据如上的函数,用来统计空闲内存,提交内存和保留内存的大小。

 

    为了方便函数的书写,我们先定义一个结构体,分别用来存储这三种类型内存:

    

  1. struct RegionSize   
  2. {  
  3.   DWORD dwFree;  
  4.   DWORD dwReserve;  
  5.   DWORD dwCommit;  
  6.  };  

 

    然后我们的函数如下形式:

  1. BOOL GetRegionSizeFromMemoryBase(DWORD dwAddressBase,RegionSize &RegionSize)  
  2. {  
  3.  DWORD dwStartAddress = dwAddressBase;  
  4.  DWORD dwEndAddress = dwStartAddress + 0x40000000;  
  5.  DWORD dwAddress = dwStartAddress;  
  6.   
  7.  if(dwAddress >= dwEndAddress)  
  8.  {  
  9.   return FALSE;  
  10.  }  
  11.   
  12.  memset(&RegionSize,0,sizeof(RegionSize));  
  13.   
  14.  while (dwAddress < dwEndAddress)  
  15.  {  
  16.   MEMORY_BASIC_INFORMATION memoryInfo;  
  17.   SIZE_T rv = ::VirtualQuery((LPVOID)dwAddress, &memoryInfo, sizeof(memoryInfo));  
  18.   if (rv != 0)  
  19.   {  
  20.    if (memoryInfo.State == MEM_COMMIT)  
  21.    {  
  22.     RegionSize.dwCommit += memoryInfo.RegionSize;  
  23.    }  
  24.    if (memoryInfo.State == MEM_RESERVE)  
  25.    {  
  26.     RegionSize.dwReserve += memoryInfo.RegionSize;  
  27.    }  
  28.    if (memoryInfo.State == MEM_FREE)  
  29.    {  
  30.     RegionSize.dwFree += memoryInfo.RegionSize;  
  31.    }  
  32.    dwAddress += memoryInfo.RegionSize;  
  33.   }  
  34.   else  
  35.   {  
  36.    break;  
  37.   }  
  38.  }  
  39.   
  40.  return TRUE;  
  41. }  
  42.   
  43.    

    GetRegionSizeFromMemoryBase函数的dwAddressBase形参数值,我们可以使用从GetProcessEntry获得信息的th32MemoryBase字段。

 

    GetRegionSizeFromMemoryBase函数的思维也非常简单,无非就是根据State的数值类型,然后累加不同的数值而已。

 

    有了如上的函数,我们就能简单方便地获取WinCE系统进程的相关内存信息了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值