歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux服務器 >> 理解Linux上的內存使用

理解Linux上的內存使用

日期:2017/3/2 16:51:56   编辑:Linux服務器

本文是為那些經常疑惑的人准備的,“為什麼一個簡單的KDE文本編輯器要占用25M內存?”導致大多數人認為許多Linux應用程序,特別是KDE或GNOME程序都象ps報告一樣臃腫,雖然這可能是也可能不是真的,依賴於具體的程序,它通常不是真的,一些程序比它們看起來消耗更多的內存。

ps工具能為一個進程輸出許多塊有關的信息,象進程ID,當前運行狀態,資源利用情況等。其中可能輸出VSZ(代表虛擬設置大小)和RSS(駐留設置大小),它們經常被世界各地的計算機愛好者用來查看進程占用了多少內存。

例如:下面是在我電腦上用ps aux命令為KEit的輸出:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
dbunker 3468 0.0 2.7 25400 14452 ? S 20:19 0:00 kdeinit:kedit

按照ps的輸出,KEdit占用了大約25M的虛擬大小內存空間,大約14M駐留大小空間(上面報告中的兩個數字都用k為單位),看起來大部分人都喜歡隨意選擇其中一個數字來表示某個進程的真實內存占用情況。我現在暫時先不解釋VSZ和RSS之間的不同之處。不用說,前面那種認識是錯誤的!想要知道為什麼,必須先學習Linux是如何在程序中控制共享庫的。

在Linux上的大部分主要程序使用共享庫有助於確定功能,例如:一個KDE文件編輯程序將使用幾個KDE共享庫(為了允許與其他的KDE組件進行交互),幾個X庫(為了允許它顯示、拷貝和粘貼圖像)和幾個常用系統庫(為了允許它執行基本的操作)。大部分這些庫,特別是象libc這樣常用的庫,是被許多Linux程序使用的,正是由於有這些共享,Linux可以使用一個巨大的訣竅:它將只載入單個共享庫的拷貝到內存中,使用這一個拷貝就可以供每個引用它的程序使用。

許多工具不再關心這個非常通用的技巧,這可能是個好現象也可能是個壞現象;它們只是簡單地報告某個進程使用了多少內存,而不管是否是與其他進程共享了部分內存,兩個程序使用一個很大的共享庫,並且它的大小傾向於它們內存使用的總和,共享庫被計入了雙倍的大小,如果你不清楚這一點將使你產生誤解。

不幸的是,關於進程內存使用的准確表示法不是那麼容易獲得,不僅需要你理解系統是如何真實地工作的,而且還需要解決你想處理的一些困難問題,一個共享庫應該為那個使用它的進程內存使用進行計數嗎?如果一個共享庫被許多進程使用,在這些進程間它的內存使用是平均分布的嗎?或者剛好可以忽略?沒有一個確定的及快速的規則,依賴於你面對的位置你可能會有不同的答案。這下容易看出來為什麼ps不會盡力嘗試報告一個正確的內存使用總量,而是給出一個模糊的數字。

看一個進程的內存映像足以說明,讓我們來看一看那個龐大的Kedit進程的位置,要查看Kedit的內存象什麼樣子,我們將使用pmap程序(使用-d標志)


Address Kbytes Mode Offset Device Mapping08048000 40 r-x– 0000000000000000 0fe:00000 kdeinit08052000 4 rw— 0000000000009000 0fe:00000 kdeinit08053000 1164 rw— 0000000008053000 000:00000 [ anon ]40000000 84 r-x– 0000000000000000 0fe:00000 ld-2.3.5.so40015000 8 rw— 0000000000014000 0fe:00000 ld-2.3.5.so40017000 4 rw— 0000000040017000 000:00000 [ anon ]40018000 4 r-x– 0000000000000000 0fe:00000 kedit.so40019000 4 rw— 0000000000000000 0fe:00000 kedit.so40027000 252 r-x– 0000000000000000 0fe:00000 libkparts.so.2.1.040066000 20 rw— 000000000003e000 0fe:00000 libkparts.so.2.1.04006b000 3108 r-x– 0000000000000000 0fe:00000 libkio.so.4.2.040374000 116 rw— 0000000000309000 0fe:00000 libkio.so.4.2.040391000 8 rw— 0000000040391000 000:00000 [ anon ]40393000 2644 r-x– 0000000000000000 0fe:00000 libkdeui.so.4.2.040628000 164 rw— 0000000000295000 0fe:00000 libkdeui.so.4.2.040651000 4 rw— 0000000040651000 000:00000 [ anon ]40652000 100 r-x– 0000000000000000 0fe:00000 libkdesu.so.4.2.04066b000 4 rw— 0000000000019000 0fe:00000 libkdesu.so.4.2.04066c000 68 r-x– 0000000000000000 0fe:00000 libkwalletclient.so.1.0.04067d000 4 rw— 0000000000011000 0fe:00000 libkwalletclient.so.1.0.04067e000 4 rw— 000000004067e000 000:00000 [ anon ]4067f000 2148 r-x– 0000000000000000 0fe:00000 libkdecore.so.4.2.040898000 64 rw— 0000000000219000 0fe:00000 libkdecore.so.4.2.0408a8000 8 rw— 00000000408a8000 000:00000 [ anon ]…. (trimmed) …mapped: 25404K writeable/private: 2432K shared: 0K

我剪掉了許多輸出內容,剩下的與展示出來的類似,即使沒有完整的輸出,我們也可以看到一些非常有趣的內容,一個重要的內容就是注意到每一個共享庫都列出了兩次,一次為它的代碼段一次為它的數據段,代碼段具有“r-x-”樣式,而數據段具有“rw--”樣式,我們關心的只有字節數、樣式和映像欄,剩下的對於討論都是不重要的。

如果你仔細檢查輸出內容,你會發現最大字節數的行通常是包含共享庫(以lib開頭的行就是共享庫)的代碼段行,如果你找出了在進程之間所有的共享部分,它們以“writeable/private” 結束,顯示在輸出的底端,這可以理解為進程的消耗增量,因此,運行Kedit(假設所有共享庫都已經被載入了)實例大約要占用2M,這和ps報告的14或25M完全不是一回事。

這意味著什麼?

這個故事的寓意是Linux進程內存使用是一個復雜的事情,你不能僅通過運行ps來了解,當你處理一個創建了大量子進程的程序時特別真實,如Apache,ps可能報告每個Apache進程使用10M內存,實際上每個Apache進程只消耗了1M內存,在調整Apache的MaxClients參數(它決定了你的服務器能同時處理的請求數量,)設置時這個信息變得非常重要。

同時,它也適應於桌面軟件,如果你運行了KDE,但是幾乎全部使用Gnome應用程序,那麼你將為多余的(但是不同的)共享庫付出巨大的代價,因此請盡量保持要麼全部運行KDE應用程序要麼全部運行Gnome應用程序,這樣Linux就可以使用更多的內存來做其他事情(如文件緩存,它可以極大地提高文件的訪問速度)。

Copyright © Linux教程網 All Rights Reserved