Reputation: 61
How can I make a system or library call on Windows to learn the memory usage of a program running a C program?
Upvotes: 1
Views: 766
Reputation: 490138
A lot depends on what you mean by the memory used by that program. Just for an obvious example, the Windows DLLs are mapped to nearly all programs' address spaces. Do you consider that memory used by the program or not? If you have two (or more) instances of a program running, its own executable (and any DLLs) will normally be mapped to all those processes as well. At the same time, a great deal of that may only be address space -- code that hasn't been used may not be loaded into physical memory at all.
All that said, here's a program that will walk through the memory blocks for a specified process and dump out information about them. Depending on what you means by memory used by a process, you may (for example) be looking for blocks marked Private
.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
unsigned long usage;
void show_modules(HANDLE process) {
unsigned char *p = NULL;
MEMORY_BASIC_INFORMATION info;
for ( p = NULL;
VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info);
p += info.RegionSize )
{
printf("%#10.10x (%6uK)\t", info.BaseAddress, info.RegionSize/1024);
switch (info.State) {
case MEM_COMMIT:
printf("Committed");
break;
case MEM_RESERVE:
printf("Reserved");
break;
case MEM_FREE:
printf("Free");
break;
}
printf("\t");
switch (info.Type) {
case MEM_IMAGE:
printf("Code Module");
break;
case MEM_MAPPED:
printf("Mapped ");
break;
case MEM_PRIVATE:
printf("Private ");
}
printf("\t");
if ((info.State == MEM_COMMIT) && (info.Type == MEM_PRIVATE))
usage +=info.RegionSize;
int guard = 0, nocache = 0;
if ( info.AllocationProtect & PAGE_NOCACHE)
nocache = 1;
if ( info.AllocationProtect & PAGE_GUARD )
guard = 1;
info.AllocationProtect &= ~(PAGE_GUARD | PAGE_NOCACHE);
switch (info.AllocationProtect) {
case PAGE_READONLY:
printf("Read Only");
break;
case PAGE_READWRITE:
printf("Read/Write");
break;
case PAGE_WRITECOPY:
printf("Copy on Write");
break;
case PAGE_EXECUTE:
printf("Execute only");
break;
case PAGE_EXECUTE_READ:
printf("Execute/Read");
break;
case PAGE_EXECUTE_READWRITE:
printf("Execute/Read/Write");
break;
case PAGE_EXECUTE_WRITECOPY:
printf("COW Executable");
break;
}
if (guard)
printf("\tguard page");
if (nocache)
printf("\tnon-cachable");
printf("\n");
}
}
int main(int argc, char **argv) {
int pid;
if (argc != 2) {
fprintf(stderr, "Usage: %s <process ID>", argv[0]);
return 1;
}
sscanf(argv[1], "%i", &pid);
HANDLE process = OpenProcess(
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
false,
pid);
show_modules(process);
printf("Total memory used: %luKB\n", usage/1024);
return 0;
}
Upvotes: 2
Reputation: 14446
Take a look at this example using GetProcessMemoryInfo
:
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
// and compile with -DPSAPI_VERSION=1
void PrintMemoryInfo( DWORD processID )
{
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
// Print the process identifier.
printf( "\nProcess ID: %u\n", processID );
// Print information about the memory usage of the process.
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
if (NULL == hProcess)
return;
if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
{
printf( "\tPageFaultCount: 0x%08X\n", pmc.PageFaultCount );
printf( "\tPeakWorkingSetSize: 0x%08X\n",
pmc.PeakWorkingSetSize );
printf( "\tWorkingSetSize: 0x%08X\n", pmc.WorkingSetSize );
printf( "\tQuotaPeakPagedPoolUsage: 0x%08X\n",
pmc.QuotaPeakPagedPoolUsage );
printf( "\tQuotaPagedPoolUsage: 0x%08X\n",
pmc.QuotaPagedPoolUsage );
printf( "\tQuotaPeakNonPagedPoolUsage: 0x%08X\n",
pmc.QuotaPeakNonPagedPoolUsage );
printf( "\tQuotaNonPagedPoolUsage: 0x%08X\n",
pmc.QuotaNonPagedPoolUsage );
printf( "\tPagefileUsage: 0x%08X\n", pmc.PagefileUsage );
printf( "\tPeakPagefileUsage: 0x%08X\n",
pmc.PeakPagefileUsage );
}
CloseHandle( hProcess );
}
int main( void )
{
// Get the list of process identifiers.
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
{
return 1;
}
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the memory usage for each process
for ( i = 0; i < cProcesses; i++ )
{
PrintMemoryInfo( aProcesses[i] );
}
return 0;
}
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682050(v=vs.85).aspx
Upvotes: 0