1. 程式人生 > >#linux 記憶體、磁碟、程序、網路分析

#linux 記憶體、磁碟、程序、網路分析

1 記憶體

[root@localhost ~]# free -m
             total       used       free     shared    buffers     cached
Mem:         15951      13825       2125          0        145       3017
-/+ buffers/cache:      10662       5289
Swap:         8191          0       8191

[root@localhost ~]# top
top - 16:26
:48 up 778 days, 6:56, 2 users, load average: 0.00, 0.00, 0.00 Tasks: 121 total, 1 running, 120 sleeping, 0 stopped, 0 zombie Cpu(s): 0.1%us, 0.1%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 10380
root 20 0 15024 1328 1012 R 0.3 0.0 0:00.04 top 1 root 20 0 19228 1512 1224 S 0.0 0.0 0:11.94 init 2
root 20 0 0 0 0 S 0.0 0.0 0:00.20 kthreadd 3 root RT 0 0 0 0 S 0.0 0.0 0:01.76 migration/0 4 root 20 0 0 0 0 S 0.0 0.0 0:32.40 ksoftirqd/0 5 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0 [root@localhost ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda2 20G 4.8G 14G 26% / tmpfs 7.8G 0 7.8G 0% /dev/shm /dev/sda1 2.0G 87M 1.8G 5% /boot /dev/sda5 69G 491M 65G 1% /export

記憶體去哪了?

Filesystem            Size  Used Avail Use% Mounted on
tmpfs                 7.8G     0  7.8G   0% /dev/shm

1.1 /dev/shm

是一個裝置檔案,, 可以把/dev/shm看作是系統記憶體的入口, 可以把它看做是一塊物理儲存裝置,

一個tmp filesystem, 你可以通過這個裝置向記憶體中讀寫檔案, 以加快某些I/O高的操作,比如對一個大型檔案頻繁的open, write, read,

可以通過mount命令列出當前的/dev/shm的掛載的檔案系統,你可以直接對/dev/shm進行讀寫操作, 例如:

# touch /dev/shm/file1

既然是基於記憶體的檔案系統,系統重啟後/dev/shm下的檔案就不存在了。
Linux預設(CentOS)/dev/shm分割槽的大小是系統實體記憶體的50%, 雖說使用/dev/shm對檔案操作的效率會高很多,但是目前各發行軟體中卻很少有使用它的。可以通過ls /dev/shm檢視下面是否有檔案, 如果沒有就說明當前系統並沒有使用該裝置.

什麼是tmpfs和/dev/shm/?

tmpfs是Linux/Unix系統上的一種基於記憶體的檔案系統。tmpfs可以使用您的記憶體或swap分割槽來儲存檔案。
tmpfs主要儲存暫存的檔案。它有如下2個優勢 : 1. 動態檔案系統的大小。2. tmpfs 的另一個主要的好處是它閃電般的速度。

典型的 tmpfs 檔案系統會完全駐留在記憶體 RAM 中,讀寫幾乎可以是瞬間的。同時它也有一個缺點 tmpfs 資料在重新啟動之後不會保留

tmpfs是基於記憶體的檔案系統,建立時不需要使用mkfs等初始化。如想改變/dev/shm tmpfs大小,修改/etc/fstab的

devpts                  /dev/pts                devpts  gid=5,mode=620  0 0

然後執行

mount -o remount /dev/shm

tmpfs(/dev/shm)的使用及應用場景

先在/dev/shm建一個tmp目前,並與/tmp繫結。

# mkdir  /dev/shm/tmp
# chmod  1777  /dev/shm/tmp    
# mount --bind  /dev/shm/tmp  /tmp
# ls -ld /tmp
解除安裝
# umount /dev/shm

1.2 Swap

現代作業系統都實現了“虛擬記憶體”這一技術,不但在功能上突破了實體記憶體的限制,使程式可以操縱大於實際實體記憶體的空間,更重要的是,“虛擬記憶體”是隔離每個程序的安全保護網,使每個程序都不受其它程式的干擾。

在使用Windows系統時,可以同時執行多個程式,當你切換到一個很長時間沒有理會的程式時,會聽到硬碟“嘩嘩”直響。這是因為這個程式的記憶體被那些頻繁執行的程式給“偷走”了,放到了Swap區中。因此,一旦此程式被放置到前端,它就會從Swap區取回自己的資料,將其放進記憶體,然後接著執行。

並不是所有從實體記憶體中交換出來的資料都會被放到Swap中(如果這樣的話,Swap就會不堪重負),有相當一部分資料被直接交換到檔案系統。例如,有的程式會開啟一些檔案,對檔案進行讀寫(其實每個程式都至少要開啟一個檔案,那就是執行程式本身),當需要將這些程式的記憶體空間交換出去時,就沒有必要將檔案部分的資料放到Swap空間中了,而可以直接將其放到檔案裡去。如果是讀檔案操作,那麼記憶體資料被直接釋放,不需要交換出來,因為下次需要時,可直接從檔案系統恢復;如果是寫檔案,只需要將變化的資料儲存到檔案中,以便恢復。

swapoff -a  禁用swap
swapon -a   啟用

3 buffer/cache

How do you empty the buffers and cache on a Linux system?

# free && sync && echo 3 > /proc/sys/vm/drop_caches && free
$ echo "echo 1 > /proc/sys/vm/drop_caches" | sudo sh
# yum install -y libmemcached 

#pidof nginx 僅查詢程序的所有pid
# memstat -p 3535

top

VIRT:程序佔用的虛擬記憶體
RES:程序佔用的實體記憶體
SHR:程序使用的共享記憶體
S:程序的狀態。S表示休眠,R表示正在執行,Z表示僵死狀態,N表示該程序優先值為負數
%CPU:程序佔用CPU的使用率
%MEM:程序使用的實體記憶體和總記憶體的百分比
TIME+:該程序啟動後佔用的總的CPU時間,即佔用CPU使用時間的累加值。
COMMAND:程序啟動命令名稱

常用的命令(大寫):
  P:按%CPU使用率排行
  T:按TIME+排行
  M:按%MEM排行

pmap

可以根據程序檢視程序相關資訊佔用的記憶體情況,(程序號可以通過ps檢視)如下所示:
$ pmap -d 14596

ps

$ ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid'  其中rsz是是實際記憶體
$ ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid' | grep oracle |  sort -nrk5

其中rsz為實際記憶體,上例實現按記憶體排序,由大到小

linux下檢視最消耗CPU、記憶體的程序

  
1.CPU佔用最多的前5個程序:
ps auxw|head -1;ps auxw|sort -rn -k3|head -5
ps auxw|head -1是為了列印標題
2.記憶體消耗最多的前5個程序
ps auxw|head -1;ps auxw|sort -rn -k4|head -5
3.虛擬記憶體使用最多的前5個程序
ps auxw|head -1;ps auxw|sort -rn -k5|head -5

4.也可以試試
ps auxw –sort=rss
ps auxw –sort=%cpu

5.看看幾個引數含義

%MEM 程序的記憶體佔用率
VSZ 程序所使用的虛存的大小
RSS 程序使用的駐留集大小或者是實際記憶體的大小(RSS is the “resident set size” meaning physical memory used)
TTY 與程序關聯的終端(tty)

STAT 檢查的狀態:程序狀態使用字元表示的,如R(running正在執行或準備執行)、S(sleeping睡眠)、I(idle空閒)、Z (僵死)、D(不可中斷的睡眠,通常是I/O)、P(等待交換頁)、W(換出,表示當前頁面不在記憶體)、N(低優先順序任務)T(terminate終止)、W has no resident pages

D 不可中斷 Uninterruptible sleep (usually IO)
R 正在執行,或在佇列中的程序
S 處於休眠狀態
T 停止或被追蹤
Z 殭屍程序
W 進入記憶體交換(從核心2.6開始無效)
X 死掉的程序

<    高優先順序 
N    低優先順序 
L    有些頁被鎖進記憶體 
s    包含子程序 
+    位於後臺的程序組; 
l    多執行緒,克隆執行緒  multi-threaded (using CLONE_THREAD, like NPTL pthreads do) 

free(1024進位制)

$ free -g
             total       used       free     shared    buffers     cached
Mem:            15         15          0          0          2          0
-/+ buffers/cache:         12          2
Swap:           17          0         17

這臺伺服器有16G記憶體,但是結果顯示除了2G左右的檔案Buffer快取外,其餘十幾G都被確確實實的用光了。(free按1024進位制計算,總記憶體可能比實際偏小)
這裡寫圖片描述

top看了下,沒有特別吃記憶體的程式。用ps大概統計下所有程式佔用的總記憶體:

$ ps aux | awk '{mem += $6} END {print mem/1024/1024}'
0.595089

結果顯示所有程序佔用的記憶體還不到1G,實際上,因為free, ps的統計方式的差別和Copy-on-write和Shared libraries等記憶體優化機制的存在,這兩者的統計結果通常是不一樣的。但是一般情況下絕對不會相差十幾個G,肯定是有什麼隱藏的問題,Google了許久後發現,free沒有專門統計另一項快取: Slab

Slab簡介和進一步調查

Slab Allocation是Linux 2.2之後引入的一個記憶體管理機制,專門用於快取核心的資料物件,可以理解為一個核心專用的物件池,可以提高系統性能並減少記憶體碎片。(Linux 2.6.23之後,SLUB成為了預設的allocator。)
檢視Slab快取 $ cat /proc/meminfo
其中,Slab相關的資料為

Slab:             154212 kB
SReclaimable:      87980 kB
SUnreclaim:        66232 kB

SReclaimable(Linux 2.6.19+)都是clean的快取,隨時可以釋放。回到之前的記憶體問題,我查了下那臺伺服器上Slab佔用的記憶體:

$ cat /proc/meminfo | grep Slab
Slab:         12777668 kB

12G的Slab快取,有意思的是free把Slab快取統計到了used memory中,這就是之前那個問題的癥結所在了。
另外,還可以檢視/proc/slabinfo(或使用slabtop命令)來檢視Slab快取的具體使用情況。結果發現,ext3_inode_cache和dentry_cache佔用了絕大部分記憶體。

考慮到這臺伺服器會頻繁地用rsync同步大量的檔案,這個結果也並不意外。

解決問題

先說明一下,如果問題僅僅是Slab佔用了太多的記憶體(SReclaimable),那麼通常不需要太操心,因為這根本不是個問題(如果是SUnreclaim太多且不斷增長,那麼很有可能是核心有bug)。但是,如果是因為Slab佔用記憶體太多而引起了其他的問題,建議繼續閱讀。
清除Slab可回收快取
通過/proc/sys/vm/drop_caches這個配置項,可以手動清除指定的可回收快取(SReclaimable)[2]

echo 2 > /proc/sys/vm/drop_caches

上面的命令會主動釋放Slab中clean的快取(包括inode和dentry的快取),然後再free -g一下,未使用的記憶體陡增了十幾個G。。
需要注意的是,手動清除快取可能會在一段時間內降低系統性能。原則上不推薦這麼做,因為如果有需要,系統會自動釋放出記憶體供其他程式使用。

另外,手動清除Slab快取是一個治標不治本的辦法。因為問題不在Slab,而在於我們那個會引起Slab快取飆漲的程序(我這裡應該是rsync)。實際操作的時候發現,清除快取一段時間後,Slab快取很快又會“反彈”回去。如果需要治本,要麼搞定問題程序,要麼修改系統配置。

調整系統vm配置
風險預警: 調整以下系統配置可能會對系統性能造成負面影響,請仔細測試並謹慎操作。
/etc/sysctl.conf裡有幾個對記憶體管理影響比較大的配置,

  • vm.vfs_cache_pressure
    系統在進行記憶體回收時,會先回收page cache, inode cache, dentry cache和swap cache。vfs_cache_pressure越大,每次回收時,inode cache和dentry cache所佔比例越大

    vfs_cache_pressure預設是100,值越大inode cache和dentry cache的回收速度會越快,越小則回收越慢,為0的時候完全不回收(OOM!)。

  • vm.min_free_kbytes
    系統的”保留記憶體”的大小,”保留記憶體”用於低記憶體狀態下的”atomic memory allocation requests”(eg. kmalloc + GFP_ATOMIC),該引數也被用於計算開始記憶體回收的閥值,預設在開機的時候根據當前的記憶體計算所得,越大則表示系統會越早開始記憶體回收。

    min_free_kbytes過大可能會導致OOM,太小可能會導致系統出現死鎖等問題。

  • vm.swappiness
    控制系統將記憶體swap out到交換空間的積極性,取值範圍是[0, 100]。swappiness越大,系統的交換積極性越高,預設是60,如果為0則不會進行交換。

參考:
Linux System IO Monitoring
Paging
Understanding the Linux Virtual Memory Manager
Linux終端:用smem檢視記憶體佔用情況
http://os.51cto.com/art/201312/422124.htm
正確理解Linux記憶體佔用過高的問題
http://blog.licess.com/linux-memory/
Ubuntu 使用top/free檢視記憶體佔用大的原因
https://fukun.org/archives/02201800.html

linux下查詢程序佔用的記憶體方法總結
https://segmentfault.com/a/1190000004147558

lsof在Linux中的10個例子<譯>
http://kumu-linux.github.io/blog/2013/04/08/lsof/

Linux下記憶體使用分析思路
http://www.361way.com/memory-analysis/5018.html

Linux Used記憶體到底哪裡去了?
http://blog.yufeng.info/archives/2456

檢視記憶體引出的那些事兒
http://www.centoscn.com/CentOS/help/2015/0320/4937.html

Linux檢視程序的記憶體佔用情況
http://blog.csdn.net/xiyuan1999/article/details/8027386

linux伺服器常用操作和命令
http://wiki.open.qq.com/wiki/faq/linux%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%B8%B8%E7%94%A8%E6%93%8D%E4%BD%9C%E5%92%8C%E5%91%BD%E4%BB%A4