天天看點

Linux系統診斷--記憶體基礎

Linux系統診斷--記憶體基礎

1. 背景

談及linux記憶體,很多時候,我們會關注free,top等基礎指令。當系統遇到異常情況時,記憶體問題的根因追溯,現場診斷時,缺乏深層次的debug能力。本篇幅不做深層讨論,能把目前系統的問題描述清楚,是每個SRE應該具備的最基礎能力。

2. free

2.1 free指令原理

free是通過檢視 /proc/meminfo 來擷取記憶體的使用情況。但是 /proc/meminfo 這個檔案又是怎麼來的?我們先了解下 /proc 目錄:

  • /proc 是一個虛拟檔案系統,該目錄下的所有檔案都是僞檔案,該類檔案隻存在于記憶體中,并不占用空間——使用 du -sh 即可驗證,該模具路下的磁盤占用都是0。
  • /proc 下的所有檔案都是核心調用proc_create() 接口來建立的虛拟條目。
  • /proc 中的檔案,大多回報系統資訊的實時情況(程序、記憶體、cpu、裝置資訊等)。

結論:/proc/meminfo 是 /proc 檔案系統下儲存你記憶體相關資訊的“僞檔案”。

2.2 指令輸出簡介

每個發行版輸出都有一定差異,現以debian8 4.19.x發行版為例。

root@4f996feeb851:~# free -m
             total       used       free     shared    buffers     cached
Mem:          1991       1909         81          4        155        836
-/+ buffers/cache:        917       1073
Swap:         1023          1       1022           

大部分的指令輸出意思,大家可以在man文檔中找到解析,這裡不做贅述。

  • used:已使用的記憶體 used = total - free -buffers -cached
  • free:未使用的記憶體 memFree & swapFree in /proc/meminfo
  • shared:tmpfs使用的記憶體 shmem in /proc/meminfo
  • buffers:被核心緩沖去使用的記憶體
  • cached:被頁緩存和slabs使用的記憶體
  • buffers/cache:表示buffers和cache的總和
  • swap:交換分區的使用量

2.3 buffer和cache會使用記憶體嗎

答案是肯定的,先來了解下buffer和cache。

  • cache(緩存)官方定義是用來彌補高速裝置和低速裝置之間的通路速度不比對而預留的一段空間,用來加快資源的通路。簡單講就是讀的更快。
  • buffer(緩沖)是為了做資源寫入整形,計算機遇到大量的“小規模IO”時,會将其整形為少量的“大規模IO”,降低寫入次數。進而達到“寫資源”合理利用的效果。

然而,free指令所展示的buffer和cache 有點狹義的意思——free展示的buffer表示 塊裝置所占用的緩存 、free展示的cache表示普通檔案占用的the page cache(緩存頁) 。

總之,buffer和cache使用的記憶體都是用來加速Linux讀寫性能,如果有新的程序需要記憶體,系統會将buffer和cache占用的記憶體回收,并重新配置設定給程序使用。

2.4 其他記憶體概念

RSS & VSZ & PSS & USS

  • RSS(Resident Set Size):程序實際使用的實體記憶體大小,包括sharedMem。
  • VSZ(Virtual Memory Size):程序所有能夠通路到的記憶體大小,包括因為缺頁中斷,被swap出去的記憶體大小,以及sharedMem。
  • PSS(Proportional Set Size):按照比例将記憶體的大小加到RSS中。
  • USS(Unique Set Size):程序獨占的實體記憶體大小。

usedMem分為 active & inactive

  • active:表示這部分的記憶體正在被某個特定的程序使用,不太可能被收回。
  • inactive:表示這部分記憶體是被配置設定到某個不在running狀态的程序,有可能會被回收。

Linux會維護一個LRU List用來管理活動頁和非活動頁的回收。 簡單講, 越接近該List的末尾,該頁面被回收的機率就越大,反之,越接近列首,則更不易被回收。 linux核心會維護兩類LRUList——active list和inactive list,剛通路過的頁面放入active list,長時間未通路的頁面放入inactive list,核心線程kswapd會定期将active list中的頁面移至 inactive list中。

如果系統的inactive的記憶體過大,可以通過如下操作對其做回收。

sync; echo 3 > /proc/sys/vm/drop_caches

3. 虛拟記憶體

現代x86系統,計算機能夠使用的記憶體會大于其實體記憶體的上限,依靠的就是虛拟記憶體機制。Linux支援虛拟記憶體機制和實模式機制。

實模式下,計算機會直接申請實體記憶體,虛拟記憶體機制下,系統會把磁盤當成記憶體的擴充,已增加可使用的記憶體大小。并通過映射map的機制,來儲存和實體記憶體的真實對應關系。

在磁盤和記憶體之間傳送Page的活動叫做swapping或者頁面排程(paging),被用作虛拟記憶體的磁盤分區稱為swap。

可以通過線上添加swap的方式臨時緩解記憶體不足的問題,但一般不能直接作線上減少swap的操作,很有可能導緻程序的crash。具體swap配置方式見5.1swap相關配置。

4. OOM

1.What is OOM?

Out Of Memory Killer 是 Linux 的一種系統保護機制,在系統記憶體緊張時,kill掉某些程序防止系統卡死。系統通過打分機制,來實施對程序的殺死操作。預設機制是通過掃描所有程序的記憶體占用,cpu占用等因素,然後打分  (badness),分數越高,程序被kill的優先級就越高。

2.哪些行為會讓系統對程序進行打分?

  • 程序使用fork(2)調用,建立衆多子程序時,會加分(+)。
  • 程序已經運作了很長時間,或者和使用了大量的CPU時間,會減分(-)。
  • 程序的nice值如果比較低,會加分(+)。
  • 程序如果是特權程序(privileged),會減分(-)。
  • 程序如果對硬體裝置進行直接通路,會減分(-)。

3.在哪兒可以看到程序的打分?

/proc/<pid>/oom_score

4.手動調整分數

/proc//oom_adj 該檔案可以用于調整在oom發生時,哪些程序應該被kill,範圍-16 -- +15 ,預設值為0,  

特殊值-17:表示程序永遠不會被kill。

5.怎麼知道系統有沒有觸發過OOM?

/var/log/messages、/var/log/syslog 系統日志或者dmesg系統日志診斷工具等都能夠找到。

網圖如下:

Linux系統診斷--記憶體基礎

圖1

5. 記憶體相關配置

5.1 swap相關配置

  • 通過調節系統參數,來告訴計算機使用swap分區的權重。
1. 簡介
swappiness範圍0-100,預設60
0: 表示禁止使用swap
60: 預設
100: 瘋狂使用swap

2. 操作方法
# sysctl vm.swappiness=VALUE
# sysctl vm.swappiness=20
或者
# echo VALUE > /proc/sys/vm/swappiness
# echo 30 > /proc/sys/vm/swappiness           
  • 通過線上增加swap分區大小,臨時控制記憶體洩露,記憶體不夠用等異常。
1. 需要root使用者
2. 建立存儲檔案
# dd if=/dev/zero of=/home/swap2G bs=1024 count=2M
3. 安全設定
# chown root:root /home/swap2G
# chmod 0600 /home/swap2G
4. 建立liunx交換分區
# mkswap /home/swap2G
5. enable 交換分區
# swapon /home/swap2G
6. 更新fstab檔案【注意: 部分作業系統不需要】
# vim /etc/fstab
/home/swap2G none swap sw 0 0
7. 檢查是否生效
#free -m
8. 解除安裝swap分區
# swapoff /home/swap2G           

5.2 緩存相關

sync; echo 3 > /proc/sys/vm/drop_caches

0:不釋放
1:釋放頁緩存
2:釋放 dentries 和 inodes
3:釋放所有緩存           

5.3 OOM相關

  • vm.panic_on_oom

    是否在觸發 oom 機制時觸發 kernel panic。0表示關閉(推薦),1表示打開。 kernel panic是指計算機遇到了緻命的錯誤,并且他不知道該怎麼處理時的一種動作——可以類比windows的藍屏。 我們當然不希望每次計算機在oom時就直接藍屏。推薦設定為0。

  • vm.overcommit_kbytes

    用于限制程序能夠申請的最大記憶體,0表示不設定,如果設定其他數值,比如400,則程序能夠申請到的最大記憶體為 swap+400kBytes。

  • vm.overcommit_ratio

    定義了程序可以使用的最大記憶體(百分比模式),預設為50。表示配置50之後,程序不允許申請超過 swap + 50% * 實體記憶體總量 以上的記憶體。

  • vm.oom_kill_allocating_task (Linux 2.6.24+支援)

    這在記憶體不足的情況下啟用或禁用殺死OOM觸發任務。0表示禁用(預設),1表示啟用。可以了解為oom機制的開關,預設為禁用——表示要讓oom觸發器正常執行。

  • 其他有興趣的話,可以自行man proc。

6. 結語

如有纰漏歡迎指正。

我們是阿裡雲智能全球技術服務-SRE團隊,我們緻力成為一個以技術為基礎、面向服務、保障業務系統高可用的工程師團隊;提供專業、體系化的SRE服務,幫助廣大客戶更好地使用雲、基于雲建構更加穩定可靠的業務系統,提升業務穩定性。我們期望能夠分享更多幫助企業客戶上雲、用好雲,讓客戶雲上業務運作更加穩定可靠的技術,您可用釘釘掃描下方二維碼,加入阿裡雲SRE技術學院釘釘圈子,和更多雲上人交流關于雲平台的那些事。

Linux系統診斷--記憶體基礎

繼續閱讀