第十四章 探索虚拟内存
2018-03-04 20:29 szn好色仙人 阅读(261) 评论(0) 编辑 收藏 举报//1. (A):操作系统中有许多值是由系统所运行的主机决定的,如页面大小、分配粒度等,我们不应该硬编码这些值,而是应该调用 GetSystemInfo 来获取这些值 typedef struct _SYSTEM_INFO { union { DWORD dwOemId; // Obsolete field...do not use struct { WORD wProcessorArchitecture; //The processor architecture of the installed operating system /* PROCESSOR_ARCHITECTURE_AMD64 9 x64 (AMD or Intel) PROCESSOR_ARCHITECTURE_ARM 5 ARM PROCESSOR_ARCHITECTURE_ARM64 12 ARM64 PROCESSOR_ARCHITECTURE_IA64 6 Intel Itanium-based PROCESSOR_ARCHITECTURE_INTEL 0 x86 PROCESSOR_ARCHITECTURE_UNKNOWN 0xffff Unknown architecture. */ WORD wReserved; } DUMMYSTRUCTNAME; } DUMMYUNIONNAME; DWORD dwPageSize; //CPU页面大小,x86和x64机器下为4096, IA-64下为8192 LPVOID lpMinimumApplicationAddress; //给出每个进程可用地址空间的最小内存地址,一般为65536(因为存在64KB空指针赋值区) LPVOID lpMaximumApplicationAddress; //给出每个进程的私有地址空间中最大的可用内存地址 DWORD_PTR dwActiveProcessorMask; //表示当前处于活动状态的CPU,是一个位掩码 DWORD dwNumberOfProcessors; //CPU数量 DWORD dwProcessorType; //作废字段 DWORD dwAllocationGranularity; //预定地址空间区域的分配粒度,一般为65536 WORD wProcessorLevel; WORD wProcessorRevision; } SYSTEM_INFO, *LPSYSTEM_INFO; SYSTEM_INFO sysInfo = {}; GetSystemInfo(&sysInfo); //32位程序,不开启 /LARGEADDRESSAWARE 的情况:lpMaximumApplicationAddress = 0x7ffeffff //32位程序,开启 /LARGEADDRESSAWARE 的情况:lpMaximumApplicationAddress = 0xfffeffff GetSystemInfo: Retrieves information about the current system. To retrieve accurate information for an application running on WOW64, call the GetNativeSystemInfo function. GetNativeSystemInfo: Retrieves information about the current system to an application running under WOW64. If the function is called from a 64-bit application, it is equivalent to the GetSystemInfo function. IsWow64Process: Determines whether the specified process is running under WOW64. 只有当32位程序运行在64位系统上时,此函数第二个参数才会被置为 TRUE (B): BOOL WINAPI GlobalMemoryStatusEx(_Inout_ LPMEMORYSTATUSEX lpBuffer); Retrieves information about the system's current usage of both physical and virtual memory You can use the GlobalMemoryStatusEx function to determine how much memory your application can allocate without severely impacting other applications. The information returned by the GlobalMemoryStatusEx function is volatile. There is no guarantee that two sequential calls to this function will return the same information. typedef struct _MEMORYSTATUSEX { DWORD dwLength; //The size of the structure, in bytes. You must set this member before calling GlobalMemoryStatusEx. DWORD dwMemoryLoad; //A number between 0 and 100 that specifies the approximate percentage of physical memory that is in use DWORDLONG ullTotalPhys; //The amount of actual physical memory, in bytes. DWORDLONG ullAvailPhys; /*The amount of physical memory currently available, in bytes. This is the amount of physical memory that can be immediately reused without having to write its contents to disk first. It is the sum of the size of the standby, free, and zero lists.*/ DWORDLONG ullTotalPageFile; //The current committed memory limit for the system or the current process, whichever is smaller, in bytes. DWORDLONG ullAvailPageFile; /*The maximum amount of memory the current process can commit, in bytes. This value is equal to or smaller than the system-wide available commit value. To calculate the system-wide available commit value, call GetPerformanceInfo and subtract the value of CommitTotal from the value of CommitLimit.*/ DWORDLONG ullTotalVirtual; /*The size of the user-mode portion of the virtual address space of the calling process, in bytes. This value depends on the type of process, the type of processor, and the configuration of the operating system. For example, this value is approximately 2 GB for most 32-bit processes on an x86 processor and approximately 3 GB for 32-bit processes that are large address aware running on a system with 4-gigabyte tuning enabled.*/ DWORDLONG ullAvailVirtual; //The amount of unreserved and uncommitted memory currently in the user-mode portion of the virtual address space of the calling process, in bytes. DWORDLONG ullAvailExtendedVirtual; //Reserved. This value is always 0. } MEMORYSTATUSEX, *LPMEMORYSTATUSEX; BOOL WINAPI GetPerformanceInfo (PPERFORMANCE_INFORMATION pPerformanceInformation, DWORD cb); Retrieves the performance values contained in the PERFORMANCE_INFORMATION structure. cb [in] : The size of the PERFORMANCE_INFORMATION structure, in bytes. //头文件:#include <Psapi.h> //链接库:#pragma comment(lib, "psapi") typedef struct _PERFORMANCE_INFORMATION { DWORD cb; //The size of this structure, in bytes. SIZE_T CommitTotal; //The number of pages currently committed by the system. SIZE_T CommitLimit; //The current maximum number of pages that can be committed by the system without extending the paging file(s) SIZE_T CommitPeak; //The maximum number of pages that were simultaneously in the committed state since the last system reboot. SIZE_T PhysicalTotal; //The amount of actual physical memory, in pages. SIZE_T PhysicalAvailable; //The amount of physical memory currently available, in pages. SIZE_T SystemCache; //The amount of system cache memory, in pages. This is the size of the standby list plus the system working set. SIZE_T KernelTotal; //核心内存总数(单位:页面) SIZE_T KernelPaged; //分页核心内存数(单位:页面) SIZE_T KernelNonpaged; //非分页核心内存数(单位:页面) 核心内存数情况在任务管理器 性能 左下角有显示 SIZE_T PageSize; //页面大小 DWORD HandleCount; //系统当前句柄数 DWORD ProcessCount; //系统当前进程数 DWORD ThreadCount; //系统当前线程数 } PERFORMANCE_INFORMATION, *PPERFORMANCE_INFORMATION, PERFORMACE_INFORMATION, *PPERFORMACE_INFORMATION; #include <Windows.h> #include <Psapi.h> #pragma comment(lib, "psapi") int main() { PERFORMANCE_INFORMATION PerformanceInfo = {}; GetPerformanceInfo(&PerformanceInfo, sizeof PerformanceInfo); MEMORYSTATUSEX MemoryInfo = {}; MemoryInfo.dwLength = sizeof MemoryInfo; GlobalMemoryStatusEx(&MemoryInfo); char buff[1024] = {}; sprintf_s(buff, "系统已使用的物理内存百分比:%d%%, 系统实际物理内存(字节):%lld, 系统实际可用内存(字节):%lld, 系统页文件大小(字节):%lld, 系统可用页文件大小(字节):%lld, " "当前进程用户模式分区大小(字节):0x%llX, 当前进程虚拟地址空间中未保留和未提交的量(字节):%lld", MemoryInfo.dwMemoryLoad, MemoryInfo.ullTotalPhys, MemoryInfo.ullAvailPhys, MemoryInfo.ullTotalPageFile, MemoryInfo.ullAvailPageFile, MemoryInfo.ullTotalVirtual, MemoryInfo.ullAvailVirtual); /* 否 (/LARGEADDRESSAWARE:NO): 系统已使用的物理内存百分比:40%, 系统实际物理内存(字节):8524783616, 系统实际可用内存(字节):5046480896, 系统页文件大小(字节):17047678976, 系统可用页文件大小(字节):13249622016, 当前进程用户模式分区大小(字节):0x7FFE0000, 当前进程虚拟地址空间中未保留和未提交的量(字节):2134200320 是 (/LARGEADDRESSAWARE): 系统已使用的物理内存百分比:41%, 系统实际物理内存(字节):8524783616, 系统实际可用内存(字节):5017403392, 系统页文件大小(字节):17047678976, 系统可用页文件大小(字节):13203300352, 当前进程用户模式分区大小(字节):0xFFFE0000, 当前进程虚拟地址空间中未保留和未提交的量(字节):4281683968 */ bool nRe0 = MemoryInfo.ullTotalPageFile == static_cast<unsigned long long>(PerformanceInfo.CommitLimit) * PerformanceInfo.PageSize; bool nRe1 = MemoryInfo.ullAvailPageFile == static_cast<unsigned long long>(PerformanceInfo.CommitLimit - PerformanceInfo.CommitTotal) * PerformanceInfo.PageSize; bool nRe2 = MemoryInfo.ullTotalPhys == static_cast<unsigned long long>(PerformanceInfo.PhysicalTotal) * PerformanceInfo.PageSize; bool nRe3 = MemoryInfo.ullAvailPhys == static_cast<unsigned long long>(PerformanceInfo.PhysicalAvailable) * PerformanceInfo.PageSize; bool nRe = nRe0 && nRe1 && nRe2 && nRe3; //nRe = true } (C): BOOL WINAPI GetProcessMemoryInfo(HANDLE Process, PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb); Retrieves information about the memory usage of the specified process typedef struct _PROCESS_MEMORY_COUNTERS { DWORD cb; //The size of the structure, in bytes. DWORD PageFaultCount; //The number of page faults. SIZE_T PeakWorkingSetSize; //The peak working set size, in bytes. (对应任务管理器中的 峰值工作设置(内存)) SIZE_T WorkingSetSize; //The current working set size, in bytes. (对应任务管理器中的 工作设置(内存)) SIZE_T QuotaPeakPagedPoolUsage; //The peak paged pool usage, in bytes. SIZE_T QuotaPagedPoolUsage; //The current paged pool usage, in bytes. (对应任务管理器中的 分页池) SIZE_T QuotaPeakNonPagedPoolUsage; //The peak nonpaged pool usage, in bytes. SIZE_T QuotaNonPagedPoolUsage; //The current nonpaged pool usage, in bytes.(对应任务管理器中的 非页面缓存池) SIZE_T PagefileUsage; /*The Commit Charge value in bytes for this process. (对应任务管理器中的 提交大小) Commit Charge is the total amount of memory that the memory manager has committed for a running process.*/ SIZE_T PeakPagefileUsage; //The peak value in bytes of the Commit Charge during the lifetime of this process. } PROCESS_MEMORY_COUNTERS; typedef PROCESS_MEMORY_COUNTERS *PPROCESS_MEMORY_COUNTERS; //例子: PROCESS_MEMORY_COUNTERS ProcessMemoryInfo = {}; GetProcessMemoryInfo(GetCurrentProcess(), &ProcessMemoryInfo, sizeof ProcessMemoryInfo); 工作设置(内存):专用(私有)工作集(当前进程独占)中的物理内存数量与进程正在使用且可以和其他进程共享的物理内存数量的总和。因此可以这么理解,该值就是该进程所占用的总的物理内存 峰值工作设置(内存):进程的工作设置(内存)的最大值,可以这么理解,因为工作设置(内存)是波动的,这个项专门记录最大的那个值。 内存(专用工作集):工作集的子集,它专门描述某个进程正在使用且无法与其他进程共享的物理内存值。这个值对于一个进程来说也是最重要的,它代表了一个进程到底独占了多少物理内存。 内存(共享工作集):进程和可以和别的进程共享的物理内存值(注意:是可以共享的,不一定共享了)。比较常见的,譬如,加载系统的一些DLL所占用的物理内存,文件共享内存(文件映射),命名共享内存等等。 提交大小:给当前进程使用而保留的私有虚拟内存的数量,如果要查内存泄漏,可以关注这个值。new malloc VirtualAlloc 分配的内存大小。 分页池:由内核或驱动程序代表进程分配的可分页内核内存的数量。可分页内存是可以写入其他存储媒介(例如硬盘)的内存。此页面的增长通常是由于打开的句柄没有关闭造成的 非分页缓冲池:由内核或驱动程序代表进程分配的不可分页的内核内存的数量。不可分页的内存是不能写入其他存储媒介的内存。 (D): SIZE_T WINAPI VirtualQuery(__in_opt LPCVOID lpAddress, __out_bcount_part(dwLength, return) PMEMORY_BASIC_INFORMATION lpBuffer, __in SIZE_T dwLength); Retrieves information about a range of pages in the virtual address space of the calling process