圖片來源:http://www.tomshardware.com/php
序言:html
Memory(內存)是一臺計算機組成的重要部分,也是最基礎的一部分。其它基礎組件有主板、CPU、磁盤、顯卡(可獨立可集成)等。寫這篇文章源自後面的一個案例,出於想搞明白,以及分享之前關於內存方面的一些記錄的知識點。node
本文概要主要講了內存的介紹;如何正確查看系統內存使用率;對Swap分區進行介紹;如何將內存看成硬盤來加速數據讀寫,以及分享關於內存異常的案例分析;介紹了oom-killer的機制。mysql
1、內存的介紹linux
1.何爲內存nginx
內存 是一種利用半導體技術製成的存儲數據的電子設備。其電子電路中的數據以二進制方式存儲,內存的每個存儲單元稱作記憶元。內存根據存儲能力及電源關係又可分爲易失性內存(斷電後丟失),非易失性內存(斷電後持久)。git
2.內存、CPU、磁盤三者的關係github
2、如何正確查看內存的使用率web
1.free 命令查看內存使用算法
[root@docker ~]# free total used free shared buff/cache available Mem: 1883740 440288 896080 31024 547372 1256984 Swap: 0 0 0
注:本機已關閉swap分區。
2.top 查看進程使用的內存
可指定進程查看,不加參數顯示全部的進程,以及概覽。
[root@docker ~]# top -p `pgrep nginx|head -n 1` ...省略 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 26826 root 20 0 45816 1000 0 S 0.0 0.1 0:00.00 nginx
註釋:
第一行,顯示了默認的字段,另top狀態下,可輸入 f 鍵,進行選擇其它字段,如DATA、SWAP等
第二行,顯示字段的值。這裏說下進程RES (駐留內存空間)和%MEM的關係,%MEM 是該進程佔用系統物理total內存的百分比。RES計算方式:total*%MEM=RES;VIRT包括所須要的代碼、數據和共享庫。
3.vmstat 查看虛擬內存使用以及swap分區 和系統、cpu的io 報告
[root@docker ~]# vmstat procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 4 0 0 858708 15756 571772 0 0 6 49 16 0 8 0 92 0 0
3、Swap——與內存緊密相關的交換空間
1.Swap 用途介紹
當物理內存(RAM)的數量已滿時,會使用Linux中的swap交換空間。若是系統須要更多內存資源而且RAM已滿,則內存中的非活動頁面將移動到交換空間中。雖然交換空間能夠幫助機器使用少許的RAM,但不該該被認爲是更多RAM的替代品。由於交換空間位於硬盤驅動器上,訪問時間比物理內存慢的不少。發生的交換越多,系統越慢。
Linux有兩種形式的交換空間:交換分區和交換文件。交換分區是僅用於交換的硬盤的獨立部分,沒有其餘文件能夠存放在那裏。交換文件是位於系統和數據文件之間在文件系統中的一個特殊文件。另外,swap 空間通常設置物理內存的2倍。
2.啓用或禁止交換空間
3.如何啓用或禁用交換空間
查看當前swap空間狀態
root@docker ~]# swapon -s 文件名 類型 大小 已用 權限 /mnt/os_swap file 4194300 0 -1
禁用swap空間
[root@docker ~]# swapoff -a
啓用swap空間(這裏使用的文件形式做爲swap分區)
[root@docker ~]# swapon /mnt/os_swap
4.建立swap分區大小
在當前的文件系統裏,用dd或者fallocate(更快更簡單)建立一個用於swap分區的文件:
[root@docker ~]# dd if=/dev/zero of=/mnt/os_swap bs=1M count=4096
或
[root@docker ~]# fallocate -l 4G /mnt/os_swap
修改該文件權限爲600
[root@docker ~]# chmod 600 /mnt/os_swap
使用mkswap命令將文件建成一個交換空間(也可在最後用 -p size 指定劃分給swap空間的大小,默認使用整個file 大小)
[root@docker ~]# mkswap /mnt/os_swap mkswap: /mnt/os_swap: warning: wiping old swap signature. 正在設置交換空間版本 1,大小 = 4194300 KiB 無標籤,UUID=fc870bd5-c823-4e70-9d14-966543a52db2
使用swap分區,並檢查swap空間大小
[root@docker ~]# swapon /mnt/os_swap [root@docker ~]# swapon -s 文件名 類型 大小 已用 權限 /mnt/os_swap file 4194300 0 -1
首先找到一個大小合適的磁盤分區,分區類型選擇82-Linux Swap。而後以後和上述相似,用mkswap命令建立啓用swap分區。並用swapon /dev/vdb1(vdb1爲分區設備)命令啓用swap分區。
5.swappiness-系統何時開始使用交換空間
當咱們設置啓用swap分區後,系統會在什麼狀況下使用交換空間?這要從物理RAM內存使用狀況來看,系統內核參數定義了這個界限:vm.swappiness,該參數取值範圍在0-100之間,它定義了當系統剩餘內存是總內存的多少百分比後,即開始使用交換空間。(暫時對這句話保持質疑,通過多方內存使用的測試,系統在由RAM轉向Swap空間時並無一個固定的剩餘內存值!如你有相關計算方式,還望不吝賜教,謝謝!)
vm.swappiness 默認值是60。swappiness參數的值越高,表示內核將會更積極地從內存到交換空間中移動數據。經測試
當值爲0時,系統可用內存在使用完後再使用swap進行交換。
當值爲1時,和0的區別不大。
推薦在數據庫讀寫數據密集的應用中禁用swap交換空間或者設置更低的vm.swappiness值,避免更多的硬盤IO操做,以此做爲提升讀寫速度的一個方式。
4、如何將內存看成磁盤使用來加速數據讀寫
1.內存文件系統介紹
圖片來源:www.thomas-krenn.com
如上圖所示,利用內存做爲特殊文件系統,目前知道的方式有3種,RAMdisk、ramfs、tmpfs。
ramdisk:RAM disk是使用主系統內存做爲塊設備的一種方式。它也可用於臨時文件系統的加密工做,由於內容在從新啓動時將被擦除。因爲這個塊設備大小是固定的,所以安裝存放在其上面的文件系統是固定的大小。
ramfs:Ramfs是一個很是簡單的文件系統,用於導出Linux的磁盤緩存 機制(頁面緩存和dentry緩存)基於RAM的文件系統,能夠動態的根據須要調整大小(前提不超過總RAM的狀況)。一般,文件都被Linux緩存在內存中,數據頁從後備存儲(一般是安裝文件系統的塊設備)中讀取並被保存 防止它再次須要,但標記爲乾淨(可自由使用的),以防萬一 虛擬內存系統須要其餘內存。但ramfs 是沒有後備存儲的,像往常同樣,寫入ramfs的文件分配 dentry和頁面緩存,可是沒有地方可寫。這意味着頁面從未被標記爲乾淨,所以當VM正在尋找回收內存時,它們不能被釋放 。除非關機斷電。
tmpfs:將全部文件保存在虛擬內存中的文件系統。tmpfs中的全部內容都是臨時的,由於在你的硬盤上不會有文件被建立。若是卸載tmpfs實例, 存儲在其中的一切都丟失。若是你umount tmpfs文件系統,存儲在裏面的內容將丟失。tmpfs能夠將全部內容放入內核內部緩存並增加收縮以容納它包含的文件,並可以交換不須要的頁面到swap交換空間。因爲tmpfs 徹底位於頁面緩存和交換中,全部tmpfs頁面將在/proc/meminfo 和‘shared’ 中顯示爲 」Shmem「
2.它們三的簡單比較
ramfs與ramdisk比較:使用ram disk還須要沒必要要地將僞造塊設備中的內存複製到頁面緩存(並複製更改),以及建立和銷燬dentries。此外,它還須要一個文件系統驅動程序(如ext2)來格式化和解釋這些數據。與ramfs相比,這浪費了內存(和內存總線帶寬),爲CPU創造了沒必要要的工做,並污染了CPU高速緩存。更重要的一點,ramfs的全部的工做都發生在_anyway_,由於全部文件訪問都經過頁面和dentry緩存。 RAM disk是沒必要要的; ramfs在內部更簡單,使用起來更靈活,大小可隨着須要的空間而動態增長或減少。
本文原文出自飛走不可,若有轉載,還請註明出處,如 飛走不可:http://www.cnblogs.com/hanyifeng/p/6915399.html
ramfs與tmpfs比較:ramfs的一個缺點是你能夠持續的往裏面寫入數據,直到填滿全部的內存,而且VM沒法釋放它,由於VM認爲文件應該寫入後備存儲(而不是交換空間),可是ramfs 它沒有任何後備存儲。所以,只有root(或受信任的用戶)才容許對ramfs mount進行寫訪問。建立一個名爲tmpfs的ramfs派生物,以增長大小限制和能力,將數據寫入swap交換空間。普通用戶也能夠容許寫入權限 tmpfs掛載。
3.如何設置ramfs
建立一個目錄,用於掛載ramfs
[root@docker ~]# mkdir /ramfs_test
掛載ramfs到上一步建立的目錄中
[root@docker ~]# mount -t ramfs ramfs /ramfs_test/ 檢查 [root@docker ~]# mount |grep ramfs_test ramfs on /ramfs_test type ramfs (rw,relatime)
測試一下ramfs與磁盤io讀寫的比較,一目瞭然。
[root@docker ~]# dd if=/dev/zero of=/ramfs_test/testfile.ramfs bs=1M count=1000 記錄了1000+0 的讀入 記錄了1000+0 的寫出 1048576000字節(1.0 GB)已複製,0.60369 秒,1.7 GB/秒 [root@docker ~]# dd if=/dev/zero of=/tmp/testfile.ramfs bs=1M count=1000 記錄了1000+0 的讀入 記錄了1000+0 的寫出 1048576000字節(1.0 GB)已複製,13.3286 秒,78.7 MB/秒
另一個須要說明,網上大部分文章說掛載ramfs時,能夠指定maxsize,即便用的最大的內存,通過測試,size(maxsize)參數沒有生效,我使用如下命令進行掛載:
[root@docker ~]# mount -t ramfs ramfs /ramfs_test -o size=1024M && mount | grep ramfs ramfs on /ramfs_test type ramfs (rw,relatime,size=1024M)
而後放入一個大於1G的文件,並檢查大小
[root@docker ~]# dd if=/dev/zero of=/ramfs_test/testramfs.file bs=1M count=1200 記錄了1200+0 的讀入 記錄了1200+0 的寫出 1258291200字節(1.3 GB)已複製,0.78763 秒,1.6 GB/秒 [root@docker ~]# ll -h /ramfs_test/testramfs.file -rw-r--r-- 1 root root 1.2G 6月 2 09:04 /ramfs_test/testramfs.file
從上面能夠看出,使用ramfs做文件系統,並無受到限制,因此它有可能佔用系統所有的RAM,並致使系統死鎖,沒法進行操做,系統內核將崩潰。因此這裏在使用ramfs時,要慎重考慮使用場景,避免程序故障或內存溢出致使系統崩潰,必須重啓才能解決!另外查看了mount的man 手冊,掛載ramfs內容時只有如下內容:
Mount options for ramfs Ramfs is a memory based filesystem. Mount it and you have it. Unmount it and it is gone. Present since Linux 2.3.99pre4. There are no mount options.
而,size參數只適用於tmpfs!
Mount options for tmpfs size=nbytes Override default maximum size of the filesystem. The size is given in bytes, and rounded up to entire pages. The default is half of the memory. The size parameter also accepts a suffix % to limit this tmpfs instance to that percentage of your physical RAM: the default, when neither size nor nr_blocks is specified, is size=50%
4.如何設置tmpfs
和ramfs有點相似,先建立一個目錄,用於掛載tmpfs
[root@docker ~]# mkdir /tmpfs_test
使用mount命令掛載到tmpfs_test目錄中,並檢查掛載狀況
[root@docker ~]# mount -t tmpfs -o size=1G tmpfs /tmpfs_test && mount |grep tmpfs_test tmpfs on /tmpfs_test type tmpfs (rw,relatime,size=1048576k)
如今咱們使用dd來測試一下速度,並檢查下size 限制空間的效果
[root@docker ~]# dd if=/dev/zero of=/tmpfs_test/testtmpfs.file bs=1M count=1100 dd: error writing ‘/tmpfs_test/testtmpfs.file’: No space left on device 1025+0 records in 1024+0 records out 1073741824 bytes (1.1 GB) copied, 0.497443 s, 2.2 GB/s
從上面的提示能夠看出,空間已經不夠,如今看下實際存入的文件大小
[root@docker ~]# ls -l --block-size=K /tmpfs_test/testtmpfs.file -rw-r--r-- 1 root root 1048576K Jun 2 12:16 /tmpfs_test/testtmpfs.file
從ls的輸出能夠看到,實際存入的文件大小,恰好是size限制的大小。很明顯,size起到了避免系統RAM/SWAP內存被tmpfs 所有填滿的狀況。也體現了tmpfs 比ramfs的優點所在。因此推薦使用tmpfs。
下面是以前tmpfs介紹中所說的tmpfs在/proc/meminfo 以及shared 顯示。
[root@docker ~]# free -m && echo '-------------------------/proc/meminfo' && cat /proc/meminfo |grep Shmem total used free shared buff/cache available Mem: 1839 268 174 1024 1397 393 Swap: 0 0 0 -------------------------/proc/meminfo Shmem: 1048964 kB
5、常見內存不足或內存溢出致使的故障分析
1.一次內存異常致使應用被kill的案例
某臺應用沒法提供服務,主機sshd沒法訪問,通訊異常。使用vnc鏈接到本地終端後,發現終端界面上報如下錯誤日誌,也沒法進行操做:
INFO: task sh:12628 blocked for more than 120 seconds.Not tainted 2.6.32-431.el6.x86 #1 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
上述錯誤,只是警告提示,跟系統內核參數vm.dirty_ratio有關係,後面會專門的介紹。 因爲該主機沒法響應任何操做,系統也登錄不進去,只有斷電重啓了(這裏也可看出系統日誌收集到某個中心節點的好處Y(^_^)Y)。重啓後觀察系統messages日誌,下面是日誌的一部分,這裏有完整的日誌,有興趣的能夠下載看下:
May 19 00:31:07 robot-web kernel: VFS: file-max limit 65535 reached May 19 00:31:30 robot-web kernel: VFS: file-max limit 65535 reached May 19 00:32:24 robot-web kernel: sh invoked oom-killer: gfp_mask=0x84d0, order=0, oom_adj=0, oom_score_adj=0 May 19 00:32:24 robot-web kernel: sh cpuset=/ mems_allowed=0 May 19 00:32:24 robot-web kernel: Pid: 20387, comm: sh Not tainted 2.6.32-431.el6.x86_64 #1 May 19 00:32:24 robot-web kernel: Call Trace: May 19 00:32:24 robot-web kernel: [<ffffffff810d05b1>] ? cpuset_print_task_mems_allowed+0x91/0xb0 May 19 00:32:24 robot-web kernel: [<ffffffff81122960>] ? dump_header+0x90/0x1b0 May 19 00:32:24 robot-web kernel: [<ffffffff8122798c>] ? security_real_capable_noaudit+0x3c/0x70 May 19 00:32:24 robot-web kernel: [<ffffffff81122de2>] ? oom_kill_process+0x82/0x2a0 May 19 00:32:24 robot-web kernel: [<ffffffff81122d21>] ? select_bad_process+0xe1/0x120 May 19 00:32:24 robot-web kernel: [<ffffffff81123220>] ? out_of_memory+0x220/0x3c0 May 19 00:32:24 robot-web kernel: [<ffffffff8112fb3c>] ? __alloc_pages_nodemask+0x8ac/0x8d0 May 19 00:32:24 robot-web kernel: [<ffffffff81167a9a>] ? alloc_pages_current+0xaa/0x110 May 19 00:32:24 robot-web kernel: [<ffffffff8104ee9b>] ? pte_alloc_one+0x1b/0x50 May 19 00:32:24 robot-web kernel: [<ffffffff81146412>] ? __pte_alloc+0x32/0x160 May 19 00:32:24 robot-web kernel: [<ffffffff8114b220>] ? handle_mm_fault+0x1c0/0x300 May 19 00:32:24 robot-web kernel: [<ffffffff8104a8d8>] ? __do_page_fault+0x138/0x480 May 19 00:32:24 robot-web kernel: [<ffffffff8152d45e>] ? do_page_fault+0x3e/0xa0 May 19 00:32:24 robot-web kernel: [<ffffffff8152a815>] ? page_fault+0x25/0x30 May 19 00:32:24 robot-web kernel: [<ffffffff8152d45e>] ? do_page_fault+0x3e/0xa0 May 19 00:32:24 robot-web kernel: [<ffffffff8152a815>] ? page_fault+0x25/0x30 May 19 00:32:24 robot-web kernel: Mem-Info: May 19 00:32:24 robot-web kernel: Node 0 DMA per-cpu: May 19 00:32:24 robot-web kernel: CPU 0: hi: 0, btch: 1 usd: 0 May 19 00:32:24 robot-web kernel: CPU 1: hi: 0, btch: 1 usd: 0 May 19 00:32:24 robot-web kernel: CPU 2: hi: 0, btch: 1 usd: 0 May 19 00:32:24 robot-web kernel: CPU 3: hi: 0, btch: 1 usd: 0 May 19 00:32:24 robot-web kernel: Node 0 DMA32 per-cpu: May 19 00:32:24 robot-web kernel: CPU 0: hi: 186, btch: 31 usd: 0 May 19 00:32:24 robot-web kernel: CPU 1: hi: 186, btch: 31 usd: 0 May 19 00:32:24 robot-web kernel: CPU 2: hi: 186, btch: 31 usd: 0 May 19 00:32:24 robot-web kernel: CPU 3: hi: 186, btch: 31 usd: 0 May 19 00:32:24 robot-web kernel: Node 0 Normal per-cpu: May 19 00:32:24 robot-web kernel: CPU 0: hi: 186, btch: 31 usd: 0 May 19 00:32:24 robot-web kernel: CPU 1: hi: 186, btch: 31 usd: 0 May 19 00:32:24 robot-web kernel: CPU 2: hi: 186, btch: 31 usd: 0 May 19 00:32:24 robot-web kernel: CPU 3: hi: 186, btch: 31 usd: 0 May 19 00:32:24 robot-web kernel: active_anon:1459499 inactive_anon:284686 isolated_anon:0 May 19 00:32:24 robot-web kernel: active_file:54 inactive_file:45 isolated_file:0 May 19 00:32:24 robot-web kernel: unevictable:0 dirty:0 writeback:0 unstable:0 May 19 00:32:24 robot-web kernel: free:26212 slab_reclaimable:6599 slab_unreclaimable:53001 May 19 00:32:24 robot-web kernel: mapped:697 shmem:793 pagetables:131666 bounce:0 May 19 00:32:24 robot-web kernel: Node 0 DMA free:15728kB min:124kB low:152kB high:184kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15340kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:0kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes May 19 00:32:24 robot-web kernel: lowmem_reserve[]: 0 3000 8050 8050 May 19 00:32:24 robot-web kernel: Node 0 DMA32 free:45816kB min:25140kB low:31424kB high:37708kB active_anon:1983180kB inactive_anon:496216kB active_file:28kB inactive_file:72kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:3072092kB mlocked:0kB dirty:0kB writeback:0kB mapped:2000kB shmem:1912kB slab_reclaimable:3200kB slab_unreclaimable:82768kB kernel_stack:10296kB pagetables:147684kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:1 all_unreclaimable? no May 19 00:32:24 robot-web kernel: lowmem_reserve[]: 0 0 5050 5050 May 19 00:32:24 robot-web kernel: Node 0 Normal free:43304kB min:42316kB low:52892kB high:63472kB active_anon:3854816kB inactive_anon:642528kB active_file:188kB inactive_file:108kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:5171200kB mlocked:0kB dirty:0kB writeback:0kB mapped:788kB shmem:1260kB slab_reclaimable:23196kB slab_unreclaimable:129236kB kernel_stack:26800kB pagetables:378980kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:59 all_unreclaimable? no May 19 00:32:24 robot-web kernel: lowmem_reserve[]: 0 0 0 0 May 19 00:32:24 robot-web kernel: Node 0 DMA: 2*4kB 1*8kB 2*16kB 2*32kB 2*64kB 1*128kB 0*256kB 0*512kB 1*1024kB 1*2048kB 3*4096kB = 15728kB May 19 00:32:24 robot-web kernel: Node 0 DMA32: 340*4kB 76*8kB 461*16kB 264*32kB 132*64kB 62*128kB 12*256kB 5*512kB 0*1024kB 1*2048kB 1*4096kB = 45952kB May 19 00:32:24 robot-web kernel: Node 0 Normal: 9334*4kB 326*8kB 2*16kB 8*32kB 4*64kB 2*128kB 2*256kB 0*512kB 0*1024kB 1*2048kB 0*4096kB = 43304kB May 19 00:32:24 robot-web kernel: 30346 total pagecache pages May 19 00:32:24 robot-web kernel: 29453 pages in swap cache May 19 00:32:24 robot-web kernel: Swap cache stats: add 691531, delete 662078, find 1720814/1738009 May 19 00:32:24 robot-web kernel: Free swap = 0kB May 19 00:32:24 robot-web kernel: Total swap = 2064376kB May 19 00:32:24 robot-web kernel: 0 8384 26517 56 1 0 0 sh May 19 00:32:24 robot-web kernel: [ 8385] 0 8385 64694 2309 2 0 0 php May 19 00:32:24 robot-web kernel: [ 8386] 0 8386 26517 56 2 0 0 sh May 19 00:32:24 robot-web kernel: [ 8387] 0 8387 26517 57 0 0 0 sh May 19 00:32:24 robot-web kernel: [ 8388] 0 8388 26517 55 1 0 0 sh May 19 00:32:24 robot-web kernel: [ 8402] 0 8402 26517 56 0 0 0 sh May 19 00:32:24 robot-web kernel: [ 8887] 93 8887 23967 272 1 0 0 sendmail May 19 00:32:24 robot-web kernel: [15917] 0 15917 64760 2347 3 0 0 php May 19 00:32:24 robot-web kernel: [15921] 0 15921 64760 2351 3 0 0 php May 19 00:32:24 robot-web kernel: [15923] 0 15923 64760 2349 2 0 0 php May 19 00:32:24 robot-web kernel: [15925] 0 15925 64696 2343 3 0 0 php May 19 00:32:24 robot-web kernel: [15950] 0 15950 64760 2346 3 0 0 php
我篩選了幾條,主要內容有如下部分:
1 May 19 00:31:30 robot-web kernel: VFS: file-max limit 65535 reached 2 ... 3 4 May 19 00:32:24 robot-web kernel: Free swap = 0kB 5 May 19 00:32:24 robot-web kernel: Total swap = 2064376kB 6 ... 7 8 May 19 00:32:24 robot-web kernel: [20477] 0 20477 26518 55 3 0 0 sh 9 May 19 00:32:24 robot-web kernel: Out of memory: Kill process 1572 (mysqld) score 3 or sacrifice child 10 May 19 00:32:24 robot-web kernel: Killed process 1572, UID 500, (mysqld) total-vm:452564kB, anon-rss:5400kB, file-rss:40kB 11 May 19 00:32:24 robot-web kernel: sh invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
從日誌中能夠看到兩個問題,1是系統打開文件句柄數到達設置上限;2是內存不足,swap交換空間都用完了,觸發了內存Oom-Killer,由oom-killer根據算法選擇了mysqld,將其殺死(稍後將會說下oom-killer是怎麼選擇的)。按理應該系統這時就能夠恢復的,可是當時系統內的crontabd 裏有每10秒執行的sh任務,且這些命令運行完沒有正常釋放,致使進程鏈接數太多,佔用的內存超過了系統的可用內存。因此猜想這是系統沒法響應任何操做的根本緣由,只能重啓。
重啓系統恢復正常後,根據以上出現的問題,對系統進行了調優工做。主要包括如下幾個部分:
臨時: echo 0 > /proc/sys/kernel/hung_task_timeout_secs 或 sysctl -w hung_task_timeout_secs=0 永久 echo 「kernel.hung_task_timeout_secs = 0」 >>/etc/sysctl.conf sysctl -p
增長系統物理內存到16G,並修改用戶open files限制數爲1048576 計算是每4M內存打開256個文件數,即:(16G*1024)M/4M *256。
臨時: ulimit -n 1048576 或 echo "ulimit -n 1048576" >> /etc/profile 永久:編寫/etc/security/limits.conf,根據提示在末行添加
臨時: echo 1048576 > /proc/sys/fs/file-max 或 sysctl -w fs.file-max=1048576 永久 echo 「fs.file-max=1048576」 >> /etc/sysctl.conf sysctl -p
臨時: sysctl -w vm.dirty_background_ratio=5 sysctl -w vm.dirty_ratio=10 永久: echo "vm.dirty_background_ratio=5" >> /etc/sysctl.conf echo "vm.dirty_ratio=10" >> /etc/sysctl.conf
sysctl -p
作了以上修改優化後,系統到目前爲止,沒有出現過異常。
2.對以上參數修改進行分析
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message
先說下這個吧。關於內核爲何提示咱們要「修改這個時間爲0,來禁用這條消息」的提示。先看下hung_task_timeout_secs的介紹,參考內核文檔:
hung_task_timeout_secs: Check interval. When a task in D state did not get scheduled for more than this value report a warning. This file shows up if CONFIG_DETECT_HUNG_TASK is enabled. 0: means infinite timeout - no checking done. Possible values to set are in range {0..LONG_MAX/HZ}.
內核定時檢測系統中處於D狀態的進程,若是其處於D狀態的時間超過了指定時間(默認120s,能夠配置),則打印相關堆棧信息,也能夠經過proc參數配置使其直接panic。
默認狀況下,Linux使用高達40%的可用內存將進行文件系統緩存。達到此標記後,文件系統將全部未完成的數據刷新到磁盤,致使全部的IO進行同步。要將此數據刷新到磁盤,默認狀況下有120秒的時間限制。在這種狀況下,IO子系統速度不夠快,能夠有120秒的時間刷新數據。因爲IO子系統響應緩慢,而且用戶進程又提出了更多的請求,系統內存將被填滿,從而致使上述截圖中的錯誤提示。
將其值修改成 0,意味着表示能夠無限超時--不檢查完成狀況。但此並不能真正的解決問題根源。
與hung_task其相關的幾個參數
[root@docker ~]# sysctl -a|grep vm.dirty vm.dirty_background_bytes = 0 vm.dirty_background_ratio = 10 vm.dirty_bytes = 0 vm.dirty_expire_centisecs = 3000 vm.dirty_ratio = 30 vm.dirty_writeback_centisecs = 500
這裏只說下其中兩個相關的參數:vm.dirty_ratio 、vm.dirty_background_ratio,如下內容出自Linux內核文檔介紹:
dirty_background_ratio Contains, as a percentage of total available memory that contains free pages and reclaimable pages, the number of pages at which the background kernel flusher threads will start writing out dirty data. The total available memory is not equal to total system memory. ============================================================== dirty_ratio Contains, as a percentage of total available memory that contains free pages and reclaimable pages, the number of pages at which a process which is generating disk writes will itself start writing out dirty data. The total available memory is not equal to total system memory.
dirty_background_ratio:是系統總內存的佔用百分比,其中包括空閒頁面和可回收頁面。後臺內核刷新線程的頁面開始寫入髒數據。即dirty data若是達到了dirty_background_ratio,則內核將在後臺執行回寫磁盤,可是應用程序仍然能夠在不阻塞的狀況下寫入頁面緩存。
dirty_ratio:包含可用頁面和可回收頁面的佔 總可用內存的百分比,產生磁盤寫入的進程將自動開始寫入髒數據。這時應用程序將阻塞並將髒頁面寫入磁盤。直到系統內的dirty page低於該值。
即先達到dirty_background_ratio,這是程序不會阻塞,等到達dirty_ratio時,程序將阻塞請求,直到將數據寫入磁盤中。這些參數的值取決於系統的運行的什麼程序,若是運行大型數據庫,建議將這些值保持小數值 background_ratio < dirty_ratio,以免I/O瓶頸以及增長系統負載。這也是做爲系統VM優化的一個點。
說下file-max
sysctl -w fs.file-max=1048576
file-max中的值表示Linux內核將要分配的文件句柄的最大數量。 每當應用程序請求文件句柄時,內核會動態分配文件句柄,但內核在應用程序關閉時並不會釋放銷燬這些文件句柄。內核會循環使用這些文件句柄。也意味着隨着時間的推移,分配的文件句柄的總數將增長,即便當前使用的文件句柄的數量可能較低。因此當您收到大量關於運行文件句柄的錯誤消息時,可能須要增長file-max值的大小。
3.什麼是oom-killer ?
介紹
OOM(Out Of Memory) Management:它有一個簡單的任務->檢查系統是否有足夠的可用內存來知足應用程序,驗證系統是否真的是內存不足,若是是這樣,請‘選擇’一個進程來殺死它。
當檢查可用內存時,所需頁面的數量做爲參數傳遞給vm_enough_memory()。除非系統管理員指定系統應該過分使用內存,不然將檢查可用內存的安裝。爲了肯定有多少頁是潛在可用的,Linux總結了如下幾個關注數據:
Total page cache 由於頁面緩存容易回收
Total free pages 由於它們已是有效可利用的
Total free swap pages 做爲用戶空間的頁面可能會被分頁換出
Total pages managed by swapper_space 儘管這重複計算了空閒的交換頁面。這是平衡的,由於事實上,插槽有時是保留的,但沒有在使用。
Total pages used by the dentry cache 易於回收的
Total pages used by the inode cache 易於回收的
若是以上添加的總頁數足以知足請求,vm_enough_memory()函數將返回true給調用者。若是返回false,調用者就知道內存不可用,一般決定將-ENOMEM返回給用戶空間。這時機器內存不足時,舊的頁幀將被回收,可是儘管回收頁面可能會發現仍是沒法釋放足夠的頁面來知足請求,若是它沒法釋放頁面幀,則調用out_of_memory() 函數來查看系統是否內存不足,而且還須要kill某進程。
不巧的是,有可能系統在沒有空閒內存可用時,只須要等待IO完成 或頁面交換到後備存儲器中(如硬盤)。因此爲了防止誤殺狀況,在決定殺死一個進程以前,它將經過如下清單檢查:
只有上述測試經過了,才能調用oom_kill()來選擇一個進程kill。
以上是2.6內核之前的幾個關注數據,2.6內核之後的,將如下信息片斷添加在一塊兒以肯定可用內存:
Total page cache 由於頁面緩存容易回收
Total free pages 由於它們已是有效可利用的
Total free swap pages 做爲用戶空間的頁面可能會被分頁換出
Slab pages with SLAB_RECLAIM_ACCOUNT set 他們是容易回收的
這些頁面減去根進程的3%預留內存,就是可用於請求的總內存量。若是內存可用,則進行檢查以確保已提交內存的總量不超過容許的閾值。
容許的閾值爲TotalRam *(OverCommitRatio / 100)+ TotalSwapPage,其中OverCommitRatio 由系統管理員設置。
以上內容參考Mel Gorman的書籍<<Understanding the Linux Virtual Memory Manager>>
注:
對swapper_space做個解釋備註,當釋放不用的物理頁面時,內核並不會當即將其放入空閒隊列(free_area),而是將其插入非活動隊列lru,便於再次時可以快速的獲得。swapper_space則用於記錄換入/換出到磁盤交換文件中的物理頁面。swapper_space是3個全局的LRU隊列其中之一,可參考做者zszmhd的內存管理的文章
對dentry(翻譯:目錄項)的解釋:它們用來實現名稱和 inode 之間的映射,有一個目錄緩存用來保存最近使用的 dentry。dentry 還維護目錄和文件之間的關係,從而支持在文件系統中移動
4.爲何oom_killer選擇了mysqld進程?
函數select_bad_process()負責選擇要殺死的進程。badness() 已改oom_badness()經過爲其檢查每一個進程累加的「ponits」並將其返回給select_bad_process()。'points'數值最高的進程,最終會被銷燬kill,除非它已經在本身釋放內存中。
進程的得分值始於其常駐內存的大小,任何子進程(內核線程除外)的獨立內存大小也會添加到該分數中;另外root 進程在計算時將會有3%的優惠,確保超級用戶的進程不被殺掉。進程的nice值會乘2計算得分,若是nice大於0即更有可能被選中;長時間運行的進程的分數會下降,運行時間越長,被選中機率越低;直接訪問硬件設備的進程分數會下降。 (刪除緣由,是在Github上看到新的oom_kill.c文件中,已去掉了相關代碼)。最後,累積的得分由/proc/pid/oom_score存儲,且該文件對用戶只讀權限。
如下是oom_kill.c文件中關於oom_badness部分的代碼:
1 unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg, 2 const nodemask_t *nodemask, unsigned long totalpages) 3 { 4 long points; 5 long adj; 6 7 if (oom_unkillable_task(p, memcg, nodemask)) 8 return 0; 9 10 p = find_lock_task_mm(p); 11 if (!p) 12 return 0; 13 14 /* 15 * Do not even consider tasks which are explicitly marked oom 16 * unkillable or have been already oom reaped or the are in 17 * the middle of vfork 18 */ 19 adj = (long)p->signal->oom_score_adj; 20 if (adj == OOM_SCORE_ADJ_MIN || 21 test_bit(MMF_OOM_SKIP, &p->mm->flags) || 22 in_vfork(p)) { 23 task_unlock(p); 24 return 0; 25 } 26 27 /* 28 * The baseline for the badness score is the proportion of RAM that each 29 * task's rss, pagetable and swap space use. 30 */ 31 points = get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS) + 32 atomic_long_read(&p->mm->nr_ptes) + mm_nr_pmds(p->mm); 33 task_unlock(p); 34 35 /* 36 * Root processes get 3% bonus, just like the __vm_enough_memory() 37 * implementation used by LSMs. 38 */ 39 if (has_capability_noaudit(p, CAP_SYS_ADMIN)) 40 points -= (points * 3) / 100; 41 42 /* Normalize to oom_score_adj units */ 43 adj *= totalpages / 1000; 44 points += adj; 45 46 /* 47 * Never return 0 for an eligible task regardless of the root bonus and 48 * oom_score_adj (oom_score_adj can't be OOM_SCORE_ADJ_MIN here). 49 */ 50 return points > 0 ? points : 1; 51 }
另外,在oom_kill.h文件中,/proc/pid/oom_adj 有取值範圍 -16~15 之間。 -17表示對此進程禁用oom。咱們能夠修改oom_adj的值,來保護某指定的重要程序。
如何檢測系統有無被oom-killer殺死的程序:可查看系統messages日誌,以及用dmesg命令。另外還能夠用dstat命令來查看當前系統中,被oom機制選中的候選者,以下:
[root@docker ~]# dstat --top-oom --out-of-memory--- kill score mysqld 61 mysqld 61
6、總結
內存管理是Linux系統內核中核心技術,重要性不言而喻,對內存的瞭解越深,更有利於咱們應用程序的開發以及運行。文中的內容部分理論知識來自互聯網(連接在文末),另外也加入了本身的分析測試理解,本着深刻學習的心理,寫下並總結了這篇文章分享給你們。若是文章中有錯誤的地方,或者能夠修改爲更好的話來表達,還望你們不吝賜教,留言私信均可以哈。另外感謝虎神給文章起的名字😏 (:對,你沒看錯,確實是寫完以後纔想的名字,主要是內存涉及了太多知識,我以爲本文也只是描述了個大概。)
本文原文出自飛走不可,若有轉載,還請註明出處,如 飛走不可:http://www.cnblogs.com/hanyifeng/p/6915399.html
參考鏈接:
https://serverfault.com/questions/85470/meaning-of-the-buffers-cache-line-in-the-output-of-free
https://www.linux.com/news/all-about-linux-swap-space
https://askubuntu.com/questions/103915/how-do-i-configure-swappiness
https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt
https://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt
https://www.kernel.org/doc/Documentation/blockdev/ramdisk.txt
http://www.vpsee.com/2013/10/how-to-configure-the-linux-oom-killer/
http://www.adminlinux.org/2009/09/tuning-rhel-4xx-5xx-file-max-maximum.html
https://www.kernel.org/doc/Documentation/sysctl/fs.txt
https://www.blackmoreops.com/2014/09/22/linux-kernel-panic-issue-fix-hung_task_timeout_secs-blocked-120-seconds-problem/
https://www.kernel.org/doc/Documentation/sysctl/vm.txt
https://msdn.microsoft.com/en-us/library/bb742613.aspx
http://www.linuxatemyram.com/index.html
http://andylin02.iteye.com/blog/858708
https://lonesysadmin.net/2013/12/22/better-linux-disk-caching-performance-vm-dirty_ratio/
https://linux-mm.org/OOM_Killer
https://www.kernel.org/doc/gorman/html/understand/understand016.html
https://github.com/torvalds/linux/blob/dd23f273d9a765d7f092c1bb0d1cd7aaf668077e/Documentation/filesystems/proc.txt