1. 程式人生 > >設定windows2008系統快取大小限制,解決伺服器執行久了因實體記憶體耗盡出僵死

設定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有任何疑問請聯絡:
[email protected]
"); 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; }