Windows內存清理工具實現——從現象到本質

目前,有很多清理內存的工具,如Wise Memory Optimizer、 MemoryZipperPlus、SweepRAM等,360安全衛士、騰訊電腦管家、魯大師等等系統工具也帶有清理內存的功能。

這些工具主要使用Windows提供的API:EmptyWorkingSet 或SetProcessWorkingSetSize 進行內存清理。

EmptyWorkingSet 強制將進程工作集中的內存儘可能多地移動到頁面文件中 (Removes as many pages as possible from the working set of the specified process.),函數原型爲:

BOOL WINAPI EmptyWorkingSet( _In_ HANDLE hProcess );

SetProcessWorkingSetSize可以設置進程工作集中內存的最大最小值(Sets the minimum and maximum working set sizes for the specified process.),函數原型爲:

BOOL WINAPI SetProcessWorkingSetSize( _In_ HANDLE hProcess, _In_ SIZE_T dwMinimumWorkingSetSize, _In_ SIZE_T dwMaximumWorkingSetSize );其中,如果後兩個參數均爲-1時,該函數效果與EmptyWorkingSet相同(The working set of the specified process can be emptied by specifying the value (SIZE_T)–1 for both the minimum and maximum working set sizes. This removes as many pages as possible from the working set. The EmptyWorkingSet function can also be used for this purpose.)。

使用上面介紹的API,我們就可以實現自己的內存清理工具:

第一步,提升程序進程權限,兩個API函數均需要傳入要清理的線程句柄,該句柄可以通過OpenProcess得到,而如果進程權限不夠,將導致打開進程失敗。

準確地說,不是提升權限,而是把令牌中禁用的權限啓用。MSDN上指出,如果需要打開其他進程並獲得所有權限,需要啓用SeDebugPrivilege權限(To open a handle to another process and obtain full access rights, you must enable the SeDebugPrivilege privilege)。

提升權限時,需要用到的API有:OpenProcessToken、LookupPrivilegeValue、AdjustTokenPrivileges、CloseHandle,MSDN上有詳細的用法講解(Enabling and Disabling Privileges in C++),在這不一一介紹了,下面給出程序提權部分代碼:

BOOL EnableDebugPrivilege { BOOL bRet = FALSE; HANDLE hToken; if (::OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, &hToken)) { LUID luid; if (::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1UL; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (::AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { bRet = TRUE; } } ::CloseHandle(hToken); } return bRet; }第二步就是遍歷系統所有進程,調用上面兩個函數傳入的只是一個進程的句柄,也就是說每次調用只針對於一個進程的內存空間,所以我們還需要遍歷整個系統的所有進程,然後獲取每個進程的句柄,將該句柄當做參數傳入上面兩個函數。遍歷系統所有進程有很多方法,這裏使用ToolHelp API獲取。其中用到3個API函數:CreateToolhelp32Snapshot、Process32First、Process32Next,MSDN上對其用法已經有詳細的介紹(Taking a Snapshot and Viewing Processes),這裏也不再一一介紹。

第三步自然就是在上面遍歷過程中調用EmptyWorkingSet 或 SetProcessWorkingSetSize 來實現清理內存。下面給出實現代碼,代碼中使用的是SetProcessWorkingSetSize函數,懶得包含EmptyWorkingSet需要的Psapi.h頭文件。

BOOL EmptyAllProcess { BOOL bRet = FALSE; HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap != INVALID_HANDLE_VALUE) { PROCESSENTRY32 pe32; pe32.dwSize = sizeof(PROCESSENTRY32); if (::Process32First(hProcessSnap, &pe32)) { do { HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); if (hProcess) { ::SetProcessWorkingSetSize(hProcess, (SIZE_T)-1, (SIZE_T)-1); ::CloseHandle(hProcess); } } while (::Process32Next(hProcessSnap, &pe32)); bRet = TRUE; } ::CloseHandle(hProcessSnap); } return bRet; }

第四步,爲了更加直觀的顯示優化後所騰出的內存空間,可以在清理前後獲取系統內存使用狀態。這裏用到GlobalMemoryStatusEx函數來獲取當前系統物理內存與虛擬內存。GlobalMemoryStatus函數也可以獲取,但在內存超過4GB時得到的結果不正確(On computers with more than 4 GB of memory, the GlobalMemoryStatus function can return incorrect information, reporting a value of –1 to indicate an overflow. )。程序中參照MSDN上的例子打印出內存的使用狀況。

程序爲了簡便,使用了控制檯工程,運行後截圖如下:

完整的程序及源代碼下載鏈接:

看了上面介紹,相信大部分人會認爲這是一個非常有效的方法,能夠騰出大量內存,明顯減小內存的佔用率。殊不知,這種伎倆其實只是一種假象,所有的努力可能只會讓事情變得更加糟糕!不信繼續往下看。

爲什麼這麼說呢,因爲使用上面兩個API並不能減小程序的內存,只不過是強制將正在運行的程序工作內存寫入Windows的頁面文件。這樣看似內存使用量是下降了,其實只不過是把內存轉到了慢速存儲之中。當程序再次需要使用到這些內存時,由於內存已經移入頁面文件,虛擬內存位置被標記爲了"不存在",這時將會產生一個缺頁中斷,也就是平常說的頁面錯誤,這時,操作系統又不得不重新將這些內存由硬盤移到內存之中。

比如你正在看一個視頻,現在先暫停它,接着使用內存清理工具來“清理”內存。清理完後,你再回過頭來繼續播放剛纔的視頻或者執行其他程序,你會發現,程序略有卡頓(對於小內存機器尢爲明顯),在卡頓過後,系統的內存又有所上升,一段時間後,內存使用量也慢慢又漲上去了。如果你在剛清理後使用某個程序並在系統任務管理器裏查看進程信息(需要在“選擇列”對話框中選中“頁面錯誤增量”),你會發現該程序的頁面錯誤增量會明顯地增加,這個時候系統就正在把內存重新搬回到工作集內存之中。

有一篇寫得很好的文章,詳細說明了這一問題,文章鏈接:點擊打開鏈接,在此順便也貼出這篇文章:

Why Memory Optimizers and RAM Boosters Are Worse ThanUseless

Many companies want to sell you “memoryoptimizers,” often as part of “PC optimization” programs. These programs areworse than useless — not only will they not speed up your computer, they’llslow it down.

Such programs take advantage ofinexperienced users, making false promises about boosting performance. Inreality, your computer knows how to manage RAM on its own. It will use RAM toincrease your computer’s performance — there’s no point in having RAM sitempty.

Is Your Computer’s RAM Filling Up? That’s Good!

Memory optimizers are based on amisunderstanding. You may look at your computer’s RAM and see it filling up —for example, you may have 4 GB of RAM and see that 3 GB is full with only 1 GBto spare. That can be surprising to some people — look how bloated modernversions of Windows are! How are you ever going to run additional programs withso little memory available?

In reality, modern operating systems arepretty good at managing memory on their own. That 3 GB of used RAM doesn’tnecessarily indicate waste. Instead, your computer uses your RAM to cache datafor faster access. Whether it’s copies of web pages you had open in yourbrowser, applications you previously opened, or any other type of data youmight need again soon, your computer hangs onto it in its RAM. When you needthe data again, your computer doesn’t have to hit your hard drive — it can justload the files from RAM.

Crucially, there’s no point inhaving RAM empty. Even if your RAM is completely full and your computer needsmore of it to run an application, your computer can instantly discard thecached data from your RAM and use that space for the application. There’s nopoint in having RAM sit empty — if it’s empty, it’s being wasted. If it’s full,there’s a good chance it can help speed up program loading times and anythingelse that would use your computer’s hard drive.

Notice that very little RAM is actually“free” in the screenshot below. The RAM is being used as a cache, but it’sstill marked as available for any program that needs to use it.

In the past, full RAM did indicate aproblem. If you were running Windows Vista on a computer with half a gig ofRAM, you could feel the computer constantly slowing down — it had to constantlyread and write to the hard drive, using the hard drive’s page file as aninefficient replacement for RAM. However, modern computers generally haveenough RAM for most users. Even low-end computers generally ship with 4GB of RAM, which should be more than enough unless you’re doing intensive gaming,running multiple virtual machines, or editing videos.

Even if RAM was a problem for you,there’s no reason to use a memory optimizer. Memory optimizers are snake oilthat are useless at best and harmful at worst.

How Memory Optimizers Work

When you use a memory optimizer, you’llsee your computer’s RAM usage go down. This may seem like an easy win — you’vedecreased RAM usage just be pressing a button, after all. But it’s not thatsimple.

Memory optimizers actually work in oneof two ways:

· They call the EmptyWorkingSet Windows API function,forcing running applications to write their working memory to the Windows pagefile.

· They quickly allocate a large amount of memory tothemselves, forcing Windows to discard cached data and write application datato the page file. They then deallocate the memory, leaving it empty.

Both of these tricks will indeed free upRAM, making it empty. However, all this does is slow things down — now theapplications you use will have to get the data they need from the page file,reading from the hard drive and taking longer to work. Any memory being usedfor cache may be discarded, so Windows will have to get the data it needs fromthe hard drive.

In other words, these programs free upfast memory by forcing data you need onto slower memory, where it will have tobe moved back to fast memory again. This makes no sense! All it accomplishes isselling you another system optimization program you don’t need.

If Windows needs RAM, it will push datato the page file or discard cached data, anyway. This all happens automaticallywhen it needs to — there’s no point in slowing things down by forcing it to happenbefore it's necessary.

Like PC cleaning apps, memoryoptimizers are a scam. They appear to be doing something positive to people whodon’t understand how memory management works, yubut they’re actually doingsomething harmful.

How to Actually “Optimize” Your Memory

If you do want to have more availableRAM, skip the memory optimizer. Instead, try to get rid of running applicationsyou don’t need — purge unnecessary programs from your system tray, disableuseless startup programs, and so on.

If you do need more RAM for what you do,try buying some more RAM. RAM is pretty cheap and it’s not too hard to installit yourself using one of the RAM installing guides available online.Just ensure you buy the correct type of RAM for your computer.

文中詳細分析了這一現象的本質。對於現在的操作系統,並不是你內存空閒得越多,程序運行得就越快。就算內存真快耗盡,操作系統也會自動丟棄掉一部分緩存數據,同時將不頻繁訪問的頁面從工作集中移出,暫時保存在內存中的“轉換列表”中,或者進一步換出到頁面文件中,完全沒有理由也沒有必要我們自己在不必要的時候做這些事。

所以,上面實現的程序只是一個簡單地展示,以便大家明白清理內存的實際原理,不建議(甚至可以說不應該)用於解決內存不足的問題。

現在,基本各種內存清理工具使用的都是上面提到的方式,有的還允許設置自動清理,程序每隔一定時間自動進行清理...... 當你明白了這些工具的實現原理後,你會發現,這類工具僅僅是一個騙局而已,它們只不過安慰一下那些不懂內存管理的人,不但沒什麼貢獻,反而會使你係統變得更慢。

除了使用這種方式,有些清理工具還進行暴力清理。這類工具自身大量申請內存,快速填滿你的內存,這時你的系統會被迫丟棄大量緩存文件,同時調用轉換操作,將其他進程的內存空間轉換到虛擬內存。之後,這類工具再突然釋放所申請的大量空間,讓你覺得騰出了很大的空間。使用這種暴力清理可能騰出比使用EmptyWorkingSet或SetProcessWorkingSetSize更多的內存空間,但在所謂的“清理”過程中的開銷也更大,最終同樣也只是讓事情變得更加糟糕。

也有部分清理內存工具,還會結束掉一些閒置的服務與一些進程的殘留項以進一步減小內存使用量(如360安全衛士)。這種方式確實有一定的效果,能真正地騰出一定的空間。但由於可以結束的進程是有限的,而且這些進程所佔內存往往不會太大,通常也不能夠騰出多少內存空間,優化效果並不會明顯。

綜上,我個人認爲,無論清理內存或者內存優化之類的工具沒什麼實用價值與實際意義。對於內存小的機器,它們只會更加拖慢你的系統;對於大內存的機器,就算它們有用,你也沒有理由去用。所以,要解決內存不夠的問題,最有效的方式就是——插內存條,插內存條,插內存條!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章