您的位置:首页 > 编程语言 > C语言/C++

【C++系统服务】监控程序内存占用

2015-06-05 08:09 435 查看
一次资源危机引发的想法

服务器只有2G内存

好烦

我还在上面挂了QQ....

那个qqexternal进程总是在不知不觉的情况下占了我200MB+的内存

一直很烦它也不知道能怎么办

想起系统服务可以运行在后台

上次就写了个 服务 用来kill到各种超100M内存的东西

当然qq.exe,vmware-vmx.exe除外啦

上次写的时候吧 还不知道怎样出查看进程占用内存然后就听网上的用了psapi.h

好麻烦 mingw不能自动链接库

后来知道了还有NtQueryInformation这个函数

然后莫名其妙就知道了返回的SYSTEM_PROCESS_INFORMATION结构体中还有进程内存大小的这个东西....

然后就 直接用了

本来在论坛问如何查看进程挂起 

后来因为昨天没网嘛 然后就借别人手机来查了一下

终于知道了原来ResumeThread的返回值就是传说中的查看挂起的标志

有了这玩意就什么都不怕了

首先先感谢这些源代码的提供者:

遍历结构 获得进程中的主线程 获得线程状态 

还有msdn知识库

NtQuerySystemInformation function (Windows)

然后直接 上代码

//Main.cpp
//Compiled success in mingw g++ 4.8.7 (Windows Server 2003 Enterprise Edition)
//Compile command:g++ -o Main.exe Main.cpp -s

#include <windows.h>
#include <stdio.h>
#include "strcamp.h"
#include <tlhelp32.h>
#include "localvalue.h"
#include "srprocess.h"
#include <wchar.h>
#include "procthread.h"

LPCWSTR LogFile=L"******";
LPSTR szSname1="MemoryGuard";

#define dfServiceType SERVICE_WIN32_OWN_PROCESS
#define dfControlAccept (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN)

SERVICE_STATUS ss1;
SERVICE_STATUS_HANDLE ssh1;
HANDLE hdMainTh,hdopThread;
DWORD dwMainTh;
bool bCallBack_MainJob;

void WINAPI ServiceMain1(DWORD,LPCSTR *);
void WINAPI ServiceControl1(DWORD);
DWORD WINAPI MainJob(LPVOID);
bool bContinueCheck(const PSYSTEM_PROCESSES,LPCSTR);
DWORD dwCheckMoney();

BOOL SSS(LPSERVICE_STATUS ss,SERVICE_STATUS_HANDLE ssh,DWORD dwcurrentstate,DWORD dwcheckpoint=0,DWORD dwwaithint=0,DWORD dwwin32exitcode=0)
{
ss->dwCurrentState=dwcurrentstate;
ss->dwCheckPoint=dwcheckpoint;
ss->dwWaitHint=dwwaithint;
ss->dwWin32ExitCode=dwwin32exitcode;
return SetServiceStatus(ssh,ss);
}

DWORD WriteLog(LPCWSTR swIn,int wType=1,LPCSTR szIn=NULL)
{
FILE * fp=stdout;
if (wType)
fp=_wfopen(LogFile,L"a");
if (!fp)
return ERROR_FILE_NOT_FOUND;
switch (wType)
{
case 1:
fwprintf(fp,L"%ws \n",swIn);
break;
default:
if (!szIn)
fwprintf(fp,L"%ws\n",swIn);
else
fwprintf(fp,L"%ws %s",swIn,szIn);
break;
}
fclose(fp);
return ERROR_SUCCESS;
}

bool bContinueCheck(const PSYSTEM_PROCESSES prw,LPCSTR szName)
{
if (prw->ProcessId==0)
return true;
if (prw->ProcessId==4)
return true;
for (int i=0;i<sizeof(ReserveProcessName)/sizeof(ReserveProcessName[0]);i++)
if (strcamp(ReserveProcessName[i],szName))
return true;
return false;
}

DWORD dwCheckMemory()
{
______EnableDebugPrivilege();
ULONG cbBuffer = 131072;
PVOID pBuffer = NULL;
NTSTATUS Status = STATUS_INFO_LENGTH_MISMATCH;
HANDLE hHeap = GetProcessHeap();
tNTQSI NtQuerySystemInformation = (tNTQSI)GetProcAddress(GetModuleHandle(("ntdll.dll")), "NtQuerySystemInformation");
while (1) {
pBuffer = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbBuffer);
if (pBuffer == NULL) {
return GetLastError();
}
Status = NtQuerySystemInformation(SystemProcessAndThreadInformation, pBuffer, cbBuffer, &cbBuffer);
if (Status == STATUS_INFO_LENGTH_MISMATCH) {
HeapFree(hHeap, 0, pBuffer);
cbBuffer *= 2;
}
else if (!NT_SUCCESS(Status)) {
HeapFree(hHeap, 0, pBuffer);
return GetLastError();
}
else {
PSYSTEM_PROCESSES infoP = NULL;
infoP = (PSYSTEM_PROCESSES)pBuffer;
while (infoP) {
char pName[256];
memset(pName, 0, sizeof(pName));
WideCharToMultiByte(CP_ACP, 0, infoP->ProcessName.Buffer, infoP->ProcessName.Length, pName, sizeof(pName), NULL, NULL);
if (bContinueCheck(infoP,pName)){
if (!infoP->NextEntryDelta) break;
infoP = (PSYSTEM_PROCESSES)(((LPBYTE)infoP) + infoP->NextEntryDelta);
continue;
}
if ((infoP->VmCounters.WorkingSetSize/1048576)>70)
if (strcamp("qqexternal.exe",pName))
for (int i=3;--i>0;)
system("taskkill /f /im qqexternal.exe");
if ((infoP->VmCounters.WorkingSetSize/1048576)>100){
hdopThread=OpenThread(THREAD_ALL_ACCESS,FALSE,GetMainThreadId(infoP->ProcessId));
bool bCheck;
if (bCheck=(ResumeThread(hdopThread)!=0))
SuspendThread(hdopThread);
else
NT_Process(infoP->ProcessId);
if (bCheck)
WriteLog(infoP->ProcessName.Buffer);

}
if (!infoP->NextEntryDelta) break;
infoP = (PSYSTEM_PROCESSES)(((LPBYTE)infoP) + infoP->NextEntryDelta);
}
if (pBuffer) HeapFree(GetProcessHeap(), 0, pBuffer);
break;
}
}
return GetLastError();
}

int main(int argc, char const * argv[])
{
if (!(argc>1 && !strcmp("-svc",argv[1]))) return 0;
SERVICE_TABLE_ENTRY STE[]={szSname1,(LPSERVICE_MAIN_FUNCTION)ServiceMain1,NULL,NULL};
StartServiceCtrlDispatcher(STE);
return 0;
}

void WINAPI ServiceMain1(DWORD dwArgc, LPCSTR * lpszArgv)
{
if (!(ssh1=RegisterServiceCtrlHandler(szSname1,ServiceControl1))) exit(ERROR_SERVICE_NOT_ACTIVE);
ss1.dwServiceType=dfServiceType;
ss1.dwControlsAccepted=dfControlAccept;
ss1.dwCurrentState=SERVICE_START_PENDING;
ss1.dwServiceSpecificExitCode=0;
ss1.dwWin32ExitCode=0;
ss1.dwCheckPoint=1;
ss1.dwWaitHint=1000;
SetServiceStatus(ssh1,&ss1);
hdMainTh=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MainJob,NULL,0,&dwMainTh);
SSS(&ss1,ssh1,SERVICE_RUNNING);
}

void WINAPI ServiceControl1(DWORD dwControl)
{
switch (dwControl)
{
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
SSS(&ss1,ssh1,SERVICE_STOP_PENDING,1,2000);
bCallBack_MainJob=true;
WaitForSingleObject(hdMainTh,INFINITE);
CloseHandle(hdMainTh);
SSS(&ss1,ssh1,SERVICE_STOPPED);
default: break;
}
}

DWORD WINAPI MainJob(LPVOID lpParamete)
{
while (1)
{
for (int i=300;i-->0;Sleep(999))
if (bCallBack_MainJob)
return 0;
dwCheckMemory();
}
return 0;
}


//localvalue.h

#pragma once
#include <windows.h>
#include <tlhelp32.h>

#define NT_SUCCESS(Status)			((NTSTATUS)(Status)>=0)
#define STATUS_SUCCESS 				0x00000000
#define STATUS_UNSUCCESSFUL 		0xC0000001
#define STATUS_NOT_IMPLEMENTED 		0xC0000002
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
#define STATUS_INVALID_PARAMETER 	0xC000000D
#define STATUS_ACCESS_DENIED 		0xC0000022
#define STATUS_BUFFER_TOO_SMALL 	0xC0000023

typedef enum _THREAD_STATE
{
StateInitialized,
StateReady,
StateRunning,
StateStandby,
StateTerminated,
StateWait,
StateTransition,
StateUnknown
}THREAD_STATE;

typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation,
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemPathInformation,
SystemProcessAndThreadInformation,
SystemCallCountInformation,
SystemDeviceInformation,
SystemProcessorPerformanceInformation,
SystemFlagsInformation,
SystemCallTimeInformation,
Sys
4000
temModuleInformation,
SystemLocksInformation,
SystemStackTraceInformation,
SystemPagedPoolInformation,
SystemNonPagedPoolInformation,
SystemHandleInformation,
SystemObjectInformation,
SystemPageFileInformation,
SystemVdmInstemulInformation,
SystemVdmBopInformation,
SystemFileCacheInformation,
SystemPoolTagInformation,
SystemInterruptInformation,
SystemDpcBehaviorInformation,
SystemFullMemoryInformation,
SystemLoadGdiDriverInformation,
SystemUnloadGdiDriverInformation,
SystemTimeAdjustmentInformation,
SystemSummaryMemoryInformation,
SystemNextEventIdInformation,
SystemEventIdsInformation,
SystemCrashDumpInformation,
SystemExceptionInformation,
SystemCrashDumpStateInformation,
SystemKernelDebuggerInformation,
SystemContextSwitchInformation,
SystemRegistryQuotaInformation,
SystemExtendServiceTableInformation,
SystemPrioritySeperation,
SystemPlugPlayBusInformation,
SystemDockInformation,
SystemPowerInformation2,
SystemProcessorSpeedInformation,
SystemCurrentTimeZoneInformation,
SystemLookasideInformation
} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;

typedef enum _KWAIT_REASON
{
Executive			= 00,
FreePage			= 01,
PageIn				= 02,
PoolAllocation		= 03,
DelayExecution		= 04,
Suspended			= 05,
UserRequest			= 06,
WrExecutive			= 07,
WrFreePage			= 8,
WrPageIn			= 9,
WrPoolAllocation	= 10,
WrDelayExecution	= 11,
WrSuspended			= 12,
WrUserRequest		= 13,
WrEventPair			= 14,
WrQueue				= 15,
WrLpcReceive		= 16,
WrLpcReply			= 17,
WrVirtualMemory		= 18,
WrPageOut			= 19,
WrRendezvous		= 20,
Spare2				= 21,
Spare3				= 22,
Spare4				= 23,
Spare5				= 24,
WrCalloutStack		= 25,
WrKernel			= 26,
WrResource			= 27,
WrPushLock			= 28,
WrMutex				= 29,
WrQuantumEnd		= 30,
WrDispatchInt		= 31,
WrPreempted			= 32,
WrYieldExecution	= 33,
WrFastMutex			= 34,
WrGuardedMutex		= 35,
WrRundown			= 36,
MaximumWaitReason	= 37
} KWAIT_REASON;

namespace NtFunctionNS
{
typedef LONG KPRIORITY;
typedef DWORD NTSTATUS;

typedef struct _CLIENT_ID {
DWORD			UniqueProcess;
DWORD			UniqueThread;
} CLIENT_ID;

typedef struct _SYSTEM_THREADS {
LARGE_INTEGER	KernelTime;
LARGE_INTEGER	UserTime;
LARGE_INTEGER	CreateTime;
ULONG			WaitTime;
PVOID			StartAddress;
CLIENT_ID		ClientId;
KPRIORITY		Priority;
KPRIORITY		BasePriority;
ULONG			ContextSwitchCount;
_THREAD_STATE	State;
KWAIT_REASON	WaitReason;
} SYSTEM_THREADS, *PSYSTEM_THREADS;

typedef NTSTATUS (WINAPI *tNTQSI)(
IN	ULONG SystemInformationClass,
OUT	PVOID SystemInformation,
IN	ULONG SystemInformationLength,
OUT	PULONG ReturnLength
);

typedef struct _UNICODE_STRING {
USHORT         Length;
USHORT         MaximumLength;
PWSTR          Buffer;
} UNICODE_STRING;

THREADENTRY32 te32={sizeof(THREADENTRY32)};
PROCESSENTRY32 pe32={sizeof(PROCESSENTRY32)};
typedef struct _VM_COUNTERS {
#ifdef _WIN64
SIZE_T			PeakVirtualSize;
SIZE_T			PageFaultCount;
SIZE_T			PeakWorkingSetSize;
SIZE_T			WorkingSetSize;
SIZE_T			QuotaPeakPagedPoolUsage;
SIZE_T			QuotaPagedPoolUsage;
SIZE_T			QuotaPeakNonPagedPoolUsage;
SIZE_T			QuotaNonPagedPoolUsage;
SIZE_T			PagefileUsage;
SIZE_T			PeakPagefileUsage;
SIZE_T			VirtualSize;
#else
SIZE_T			PeakVirtualSize;
SIZE_T			VirtualSize;
ULONG			PageFaultCount;
SIZE_T			PeakWorkingSetSize;
SIZE_T			WorkingSetSize;
SIZE_T			QuotaPeakPagedPoolUsage;
SIZE_T			QuotaPagedPoolUsage;
SIZE_T			QuotaPeakNonPagedPoolUsage;
SIZE_T			QuotaNonPagedPoolUsage;
SIZE_T			PagefileUsage;
SIZE_T			PeakPagefileUsage;
#endif
} VM_COUNTERS;

typedef struct _SYSTEM_PROCESSES {
ULONG 			NextEntryDelta;
ULONG 			ThreadCount;
ULONG 			Reserved1[6];
LARGE_INTEGER	CreateTime;
LARGE_INTEGER	UserTime;
LARGE_INTEGER	KernelTime;
UNICODE_STRING	ProcessName;
KPRIORITY		BasePriority;
ULONG			ProcessId;
ULONG			InheritedFromProcessId;
ULONG			HandleCount;
ULONG			Reserved2[2];
VM_COUNTERS	   	VmCounters;
#if _WIN32_WINNT >= 0x500
IO_COUNTERS		IoCounters;
#endif
SYSTEM_THREADS  Threads[5];
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;
LPCSTR ReserveProcessName[]={
"svchost.exe",
"winlogon.exe",
"csrss.exe",
"smss.exe",
"services.exe",
"lsass.exe",
"explorer.exe",
"vmware-vmx.exe",
"vmware-vmx-debug.exe",
"qq.exe"
};
}

using namespace NtFunctionNS;

//srprocess.h

#pragma once

#include <windows.h>
#include <tlhelp32.h>
#include <string.h>
#include "strcamp.h"

#ifndef _In_
#define _In_ inline
#endif

static bool ____HasP=false;

#define NT_Process ___SRProcess

typedef LONG (NTAPI * _____NtSuspendProcess)(IN HANDLE);
typedef LONG (NTAPI * _____NtResumeProcess)(IN HANDLE);
_____NtSuspendProcess __03NtSuspendProcess=(_____NtSuspendProcess)GetProcAddress(GetModuleHandle("ntdll"),"NtSuspendProcess");
_____NtResumeProcess __03NtResumeProcess=(_____NtResumeProcess)GetProcAddress(GetModuleHandle("ntdll"),"NtResumeProcess");

DWORD ______EnableDebugPrivilege();
LONG SuspendProcess(LPCSTR);
LONG SuspendProcess(const HANDLE);
LONG SuspendProcess(const DWORD);
LONG ResumeProcess(LPCSTR);
LONG ResumeProcess(const HANDLE);
LONG ResumeProcess(const DWORD);

template <typename T> LONG ___SRProcess(T ty,bool type=false)
{
return (type==false)?SuspendProcess(ty):ResumeProcess(ty);
}

DWORD ______EnableDebugPrivilege()
{
if (____HasP) return GetLastError();
____HasP=true;
TOKEN_PRIVILEGES _____TP;
HANDLE _____hdToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &_____hdToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &_____TP.Privileges[0].Luid);
_____TP.PrivilegeCount = 1;
_____TP.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(_____hdToken, FALSE, &_____TP, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
CloseHandle(_____hdToken);
return GetLastError();
}

LONG SuspendProcess(LPCSTR ____szProcessName)
{
______EnableDebugPrivilege();
HANDLE _____hdSnap,____hdProcess;
PROCESSENTRY32 _____pe32={sizeof(PROCESSENTRY32)};
_____hdSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
bool ____bm=Process32First(_____hdSnap,&_____pe32);
while (____bm)
{
if(strcamp(____szProcessName,_____pe32.szExeFile))
{
____hdProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,_____pe32.th32ProcessID);
__03NtSuspendProcess(____hdProcess);
CloseHandle(____hdProcess);
}
____bm=Process32Next(_____hdSnap,&_____pe32);
}
CloseHandle(_____hdSnap);
return 0;
}

LONG SuspendProcess(const HANDLE ____hdProcess)
{
______EnableDebugPrivilege();
return __03NtSuspendProcess(____hdProcess);
}

LONG SuspendProcess(const DWORD ___dwProcessId)
{
______EnableDebugPrivilege();
HANDLE ____hdProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,___dwProcessId);
LONG ____n=__03NtSuspendProcess(____hdProcess);
CloseHandle(____hdProcess);
return ____n;
}

LONG ResumeProcess(HANDLE ____hdProcess)
{
______EnableDebugPrivilege();
return __03NtResumeProcess(____hdProcess);
}

LONG ResumeProcess(const DWORD ___dwProcessId)
{
______EnableDebugPrivilege();
HANDLE ____hdProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,___dwProcessId);
LONG ____n=__03NtResumeProcess(____hdProcess);
CloseHandle(____hdProcess);
return ____n;
}

LONG ResumeProcess(LPCSTR ____szProcessName)
{
______EnableDebugPrivilege();
HANDLE _____hdSnap,____hdProcess;
PROCESSENTRY32 _____pe32={sizeof(PROCESSENTRY32)};
_____hdSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
bool ____bm=Process32First(_____hdSnap,&_____pe32);
while (____bm)
{
if(strcamp(____szProcessName,_____pe32.szExeFile))
{
____hdProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,_____pe32.th32ProcessID);
__03NtResumeProcess(____hdProcess);
}
____bm=Process32Next(_____hdSnap,&_____pe32);
}
CloseHandle(_____hdSnap);
CloseHandle(____hdProcess);
return 0;
}


//strcamp.h

#pragma once

#include <string.h>

BOOL strcamp(LPCSTR ____str1, LPCSTR ____str2)
{
int sz1=sizeof ____str1;
int sz2=sizeof ____str2;
if (sz1!=sz2) return FALSE;
char ____tmp1[1000]="";
char ____tmp2[1000]="";
return (0==strcmp(strlwr(strcpy(____tmp1,____str1)),strlwr(strcpy(____tmp2,____str2))))?TRUE:FALSE;
}

//procthread.h

//Main code copyed by http://www.codeproject.com/Questions/78801/How-to-get-the-main-thread-ID-of-a-process-known-b //author: Eugen Podsypalnikov
//website:http://www.codeproject.com/script/Membership/View.aspx?mid=36376

#pragma once

#include <windows.h>

#if (!((_WIN32_WINNT >= 0x0500) || (_WIN32_WINDOWS >= 0x0490)))
typedef HANDLE (* WINAPI _OpenThread)(IN DWORD,IN BOOL,IN DWORD);
_OpenThread OpenThread=(_OpenThread)GetProcAddress(GetModuleHandle("kernel32"),"OpenThread");
#endif

#ifndef MAKEULONGLONG
#define MAKEULONGLONG(ldw, hdw) ((ULONGLONG(hdw) << 32) | ((ldw) & 0xFFFFFFFF))
#endif

#ifndef MAXULONGLONG
#define MAXULONGLONG ((ULONGLONG)~((ULONGLONG)0))
#endif

DWORD GetMainThreadId(DWORD);

DWORD GetMainThreadId(DWORD dwProcID)
{
DWORD dwMainThreadID = 0;
ULONGLONG ullMinCreateTime = MAXULONGLONG;
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap != INVALID_HANDLE_VALUE) { //error check
THREADENTRY32 th32;
th32.dwSize = sizeof(THREADENTRY32);
for (BOOL bOK = Thread32First(hThreadSnap, &th32); bOK;bOK = Thread32Next(hThreadSnap, &th32)) {
if (th32.th32OwnerProcessID == dwProcID) {
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,FALSE, th32.th32ThreadID);
if (hThread) {
FILETIME afTimes[4] = {0};
if (GetThreadTimes(hThread, &afTimes[0], &afTimes[1], &afTimes[2], &afTimes[3])) {
ULONGLONG ullTest = MAKEULONGLONG(afTimes[0].dwLowDateTime,afTimes[0].dwHighDateTime);
if (ullTest && ullTest < ullMinCreateTime) {
ullMinCreateTime = ullTest;
dwMainThreadID = th32.th32ThreadID; // let it be main... :)
}
}
CloseHandle(hThread);
}
}
}
}
if (!hThreadSnap)
CloseHandle(hThreadSnap);
return dwMainThreadID;
}


花了三个礼拜的时间来找代码也是很不容易

很感谢那些支持我的人 他们没有让我放弃

特别感谢那个借我手机的同学 他让我成功打通了最后一个点

Copyright (C) 2015 All Rights Reserved

by:就这样征服老尼姑
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息