设置windows2008系统缓存大小限制,解决服务器运行久了因物理内存耗尽出僵死

声明:

找到服务器僵死的原因了,原因是虚拟内存设置小于物理内存.

只要虚拟内存设置为系统默认大小就不会出生僵死的现象了.

当时因为服务器内存48G,系统默认虚拟内存大小也是48G,

觉得太占硬盘空间,一时手贱,改小了虚拟内存,才会造成服务器长时间运行僵死的现象.

#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <shlwapi.h>

#pragma comment(lib, "shlwapi.lib")

#ifndef FILE_CACHE_FLAGS_DEFINED

#define FILE_CACHE_MAX_HARD_ENABLE      0x00000001
#define FILE_CACHE_MAX_HARD_DISABLE     0x00000002
#define FILE_CACHE_MIN_HARD_ENABLE      0x00000004
#define FILE_CACHE_MIN_HARD_DISABLE     0x00000008

#endif

LPTSTR lpSrvName = TEXT("SystemFileCacheLimit");
SERVICE_STATUS ServiceStatus = {0};
SERVICE_STATUS_HANDLE hStatus;

BOOL WINAPI EnablePrivileges()
{
	HANDLE hToken; 
	TOKEN_PRIVILEGES tkp; 

	if (!::OpenProcessToken(::GetCurrentProcess(), 
		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
		return( FALSE ); 

	::LookupPrivilegeValue(NULL, SE_INCREASE_QUOTA_NAME, 
		&tkp.Privileges[0].Luid); 

	tkp.PrivilegeCount = 1; 
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

	::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, 
		(PTOKEN_PRIVILEGES)NULL, 0); 

	if (::GetLastError() != ERROR_SUCCESS) 
		return FALSE; 

	return TRUE;
}

VOID WINAPI ServiceHandler(DWORD fdwControl)
{
	switch(fdwControl)
	{
	case SERVICE_CONTROL_PAUSE:
		ServiceStatus.dwCurrentState = SERVICE_PAUSED;
		break;
	case SERVICE_CONTROL_CONTINUE:
		ServiceStatus.dwCurrentState = SERVICE_RUNNING;
		break;
	case SERVICE_CONTROL_STOP:
	case SERVICE_CONTROL_SHUTDOWN:
		ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
		ServiceStatus.dwWin32ExitCode = 0;
		ServiceStatus.dwCheckPoint    = 0;
		ServiceStatus.dwWaitHint      = 0;
		SetServiceStatus(hStatus,&ServiceStatus);
		return ;
	case SERVICE_CONTROL_INTERROGATE:
		break;
	default:
		break;
	}
	SetServiceStatus(hStatus,&ServiceStatus);
	return ;
}



VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
	DWORD   status = 0;
	DWORD   specificError = 0xfffffff;
	ServiceStatus.dwServiceType        = SERVICE_WIN32;
	ServiceStatus.dwCurrentState       = SERVICE_START_PENDING;
	ServiceStatus.dwControlsAccepted   =  SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;
	ServiceStatus.dwWin32ExitCode      = 0;
	ServiceStatus.dwServiceSpecificExitCode = 0;
	ServiceStatus.dwCheckPoint         = 0;
	ServiceStatus.dwWaitHint           = 0;

	hStatus = RegisterServiceCtrlHandler(lpSrvName,(LPHANDLER_FUNCTION)ServiceHandler);
	if (hStatus==0)
	{
		return;
	}

	status = GetLastError();
	if (status!=NO_ERROR)
	{
		ServiceStatus.dwCurrentState       = SERVICE_STOPPED;
		ServiceStatus.dwCheckPoint         = 0;
		ServiceStatus.dwWaitHint           = 0;
		ServiceStatus.dwWin32ExitCode      = status;
		ServiceStatus.dwServiceSpecificExitCode = specificError;
		SetServiceStatus(hStatus, &ServiceStatus);
		
		return;
	}

	ServiceStatus.dwCurrentState       = SERVICE_RUNNING;
	ServiceStatus.dwCheckPoint         = 0;
	ServiceStatus.dwWaitHint           = 0;  
	SetServiceStatus(hStatus, &ServiceStatus);	
	
	ULONG MiniCache, MaxCache;
	TCHAR szIni[MAX_PATH] = {0};

	::GetModuleFileName(NULL, szIni, _countof(szIni));
	::PathRenameExtension(szIni, TEXT(".ini"));
	
	if (dwArgc >=4)
	{
		::WritePrivateProfileString(TEXT("参数设置"), TEXT("最大缓存"), lpszArgv[3], szIni);
		::WritePrivateProfileString(TEXT("参数设置"), TEXT("最小缓存"), lpszArgv[2], szIni);
		MiniCache = _ttol(lpszArgv[2]) * 1024 * 1024;
		MaxCache = _ttol(lpszArgv[3]) * 1024 * 1024;
	}
	else
	{
		if (PathFileExists(szIni))
		{
			MiniCache = ::GetPrivateProfileInt(TEXT("参数设置"), TEXT("最小缓存"), -1, szIni);
			MaxCache = ::GetPrivateProfileInt(TEXT("参数设置"), TEXT("最大缓存"), -1, szIni);
			MiniCache = MiniCache * 1024 * 1024;
			MaxCache = MaxCache * 1024 * 1024;
		}	
	}

	EnablePrivileges();
	::SetSystemFileCacheSize(MiniCache, MaxCache, FILE_CACHE_MAX_HARD_ENABLE|FILE_CACHE_MIN_HARD_ENABLE);

	return;
}


int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nShowCmd)
{
	SIZE_T MiniCache, MaxCache;
	DWORD dwFlags;
	TCHAR szMsg[512] = {0};
	LPWSTR* szArgList;
	int nArgs;
	
	if (!::FindWindow(TEXT("Progman"), NULL))
	{
		SERVICE_TABLE_ENTRY ServiceTable[2];
		ServiceTable[0].lpServiceName = lpSrvName;
		ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
		ServiceTable[1].lpServiceName = NULL;
		ServiceTable[1].lpServiceProc = NULL;

		StartServiceCtrlDispatcher(ServiceTable);
		return 1;
	}

	szArgList = ::CommandLineToArgvW(::GetCommandLineW(), &nArgs);
	switch(nArgs)
	{
	case 1:
		::GetSystemFileCacheSize(&MiniCache, &MaxCache, &dwFlags);
		_stprintf_s(szMsg, _countof(szMsg), TEXT("使用方法:\n\nSetSystemFileCache.exe 最小缓存限制 最大缓存限制\n比如:SetSystemFileCache.exe 128 1024\n即设置最小缓存为128MB, 最大缓存1024MB\n\n刷新系统文件缓存: SetSystemFileCache.exe -flush\n\n关闭系统文件缓存限制(系统默认):\nSetSystemFileCache.exe -disable\n\n以服务方式运行:\nSetSystemFileCache.exe 128 1024 -Service\n即设置最小缓存为128MB,最大缓存为1024MB并以服务方式运行.\n\n当前系统文件缓存限制:\n最小文件缓存:%uMB\n最大文件缓存:%uMB\n最小文件缓存开关状态: %s\n最大文件缓存开关状态: %s\n"), 
			MiniCache/1024/1024, MaxCache/1024/1024, 
			dwFlags&FILE_CACHE_MIN_HARD_ENABLE ? TEXT("开启") : TEXT("关闭"), 
			dwFlags&FILE_CACHE_MAX_HARD_ENABLE ? TEXT("开启") : TEXT("关闭"));
		::MessageBox(::GetDesktopWindow(), szMsg, TEXT("提示"), MB_ICONASTERISK);
		break;
	case 2:
		EnablePrivileges();
		if (_tcsicmp(szArgList[1], TEXT("-flush")) == 0)
		{
			if (::SetSystemFileCacheSize(-1, -1, FILE_CACHE_MAX_HARD_ENABLE|FILE_CACHE_MIN_HARD_ENABLE))
			{
				::MessageBox(GetDesktopWindow(), TEXT("刷新系统文件缓存成功!"), TEXT("提示"), MB_ICONASTERISK);
			}else
			{
				::MessageBox(GetDesktopWindow(), TEXT("刷新系统文件缓存失败!"), TEXT("提示"), MB_ICONASTERISK);
			}
		}
		else if(_tcsicmp(szArgList[1], TEXT("-disable")) == 0)
		{
			if (::SetSystemFileCacheSize(0, 0, FILE_CACHE_MAX_HARD_DISABLE|FILE_CACHE_MIN_HARD_DISABLE))
			{
				::MessageBox(GetDesktopWindow(), TEXT("已成功关闭系统文件缓存大小限制!"), TEXT("提示"), MB_ICONASTERISK);
			}else
			{
				::MessageBox(GetDesktopWindow(), TEXT("关闭系统文件缓存大小限制失败!"), TEXT("提示"), MB_ICONASTERISK);
			}
		}
		break;
	case 3:
		MiniCache = _ttol(szArgList[1])*1024*1024;
		MaxCache = _ttol(szArgList[2])*1024*1024;
		EnablePrivileges();
		
		if (::SetSystemFileCacheSize(MiniCache, MaxCache, FILE_CACHE_MAX_HARD_ENABLE|FILE_CACHE_MIN_HARD_ENABLE))
		{
			_stprintf_s(szMsg, _countof(szMsg), TEXT("设置系统文件缓存大小上限成功!\n\n当前设置: 最小缓存%dMB, 最大缓存%dMB"), MiniCache/1024/1024, MaxCache/1024/1024);
			::MessageBox(GetDesktopWindow(), szMsg, TEXT("提示"), MB_ICONASTERISK);
		}
		else
		{
			::MessageBox(GetDesktopWindow(), TEXT("设置系统文件缓存大小上限失败!"), TEXT("提示"), MB_ICONASTERISK);
		}
		
		break;
	case 4:
		if (_tcsicmp(szArgList[3], TEXT("-Service")) == 0)
		{
			TCHAR szPath[MAX_PATH] = {0};
			SERVICE_DESCRIPTION SrvDesc;
			SrvDesc.lpDescription = TEXT("Windows2008限制系统文件缓存工具\r\nBy zwfgdlc\r\n有任何疑问请联系:zwfgdlc@qq.com");
			
			SC_HANDLE hScm = ::OpenSCManager(NULL, NULL, GENERIC_READ | GENERIC_WRITE);
			::GetModuleFileName(NULL, szPath, _countof(szPath));
			
			if (hScm)
			{
				SC_HANDLE hService = ::CreateService(hScm, lpSrvName, TEXT("SetSystemFileCache"), SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, szPath, NULL, NULL, NULL, NULL, NULL);
				if (hService == NULL && ::GetLastError() == ERROR_SERVICE_EXISTS)
				{
					if (IDYES == ::MessageBox(GetDesktopWindow(), TEXT("创建服务失败!\n服务已经存在,是否删除服务?"), TEXT("警告"), MB_ICONWARNING|MB_YESNO))
					{
						hService = ::OpenService(hScm, lpSrvName, DELETE);
						if (hService!=NULL && ::DeleteService(hService))
						{
							::MessageBox(GetDesktopWindow(), TEXT("服务已删除!"), TEXT("提示"), MB_ICONASTERISK);
						}
						::CloseServiceHandle(hService);
					}
					::CloseServiceHandle(hScm);
				}
				else
				{
					::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &SrvDesc);
					if (IDYES == ::MessageBox(GetDesktopWindow(), TEXT("服务创建成功,是否立即启动服务?"), TEXT("提示"), MB_ICONASTERISK|MB_YESNO))
					{
						::StartService(hService, nArgs, (LPCTSTR*)szArgList);
					}
					::CloseServiceHandle(hService);
					::CloseServiceHandle(hScm);
				}
				
			}
		}
		
		break;
	default:
		::MessageBox(GetDesktopWindow(), TEXT("参数不正确!"), TEXT("提示"), MB_ICONWARNING);
		break;
	}

	LocalFree(szArgList);
	return 1;
}


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值