這個(gè)命令需要重新激活一下程序才可以有回收站,并且需要先執(zhí)行刪除的指令,才能夠徹底進(jìn)入回收站。
成都創(chuàng)新互聯(lián)公司專注于涼州網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠為您提供涼州營銷型網(wǎng)站建設(shè),涼州網(wǎng)站制作、涼州網(wǎng)頁設(shè)計(jì)、涼州網(wǎng)站官網(wǎng)定制、微信小程序開發(fā)服務(wù),打造涼州網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供涼州網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。
Linux 采用 Buddy 算法有效分配和釋放物理頁塊。 linux系統(tǒng)內(nèi)存管理的特點(diǎn)linux的進(jìn)程結(jié)束后,它占用的資源全部釋放,但是內(nèi)存僅僅是設(shè)置了標(biāo)志,標(biāo)志了這部分內(nèi)存已經(jīng)不再使用,可以被重新分配的。當(dāng)進(jìn)程需要內(nèi)存時(shí),linux系統(tǒng)首先從空閑內(nèi)存中...
內(nèi)存是Linux內(nèi)核所管理的最重要的資源之一。內(nèi)存管理系統(tǒng)是操作系統(tǒng)中最為重要的部分,因?yàn)橄到y(tǒng)的物理內(nèi)存總是少于系統(tǒng)所需要的內(nèi)存數(shù)量。虛擬內(nèi)存就是為了克服這個(gè)矛盾而采用的策略。系統(tǒng)的虛擬內(nèi)存通過在各個(gè)進(jìn)程之間共享內(nèi)存而使系統(tǒng)看起來有多于實(shí)際內(nèi)存的內(nèi)存容量。Linux支持虛擬內(nèi)存, 就是使用磁盤作為RAM的擴(kuò)展,使可用內(nèi)存相應(yīng)地有效擴(kuò)大。核心把當(dāng)前不用的內(nèi)存塊存到硬盤,騰出內(nèi)存給其他目的。當(dāng)原來的內(nèi)容又要使用時(shí),再讀回內(nèi)存。以下就是我為大家整理到的詳細(xì)LINUX系統(tǒng)內(nèi)存管理的知識(shí),歡迎大家閱讀!!!
LINUX系統(tǒng)教程:內(nèi)存管理的知識(shí)詳解
一、內(nèi)存使用情況監(jiān)測(cè)
(1)實(shí)時(shí)監(jiān)控內(nèi)存使用情況
在命令行使用“Free”命令可以監(jiān)控內(nèi)存使用情況
代碼如下:
#free
total used free shared buffers cached
Mem: 256024 192284 63740 0 10676 101004
-/+ buffers/cache: 80604 175420
Swap: 522072 0 522072
上面給出了一個(gè)256兆的RAM和512兆交換空間的系統(tǒng)情況。第三行輸出(Mem:)顯示物理內(nèi)存。total列不顯示核心使用的物理內(nèi)存(通常大約1MB)。used列顯示被使用的內(nèi)存總額(第二行不計(jì)緩沖)。 free列顯示全部沒使用的內(nèi)存。Shared列顯示多個(gè)進(jìn)程共享的內(nèi)存總額。Buffers列顯示磁盤緩存的當(dāng)前大小。第五行(Swap:)對(duì)對(duì)換空間,顯示的信息類似上面。如果這行為全0,那么沒使用對(duì)換空間。在缺省的狀態(tài)下,free命令以千字節(jié)(也就是1024字節(jié)為單位)來顯示內(nèi)存使用情況??梢允褂谩猦參數(shù)以字節(jié)為單位顯示內(nèi)存使用情況,或者可以使用—m參數(shù)以兆字節(jié)為單位顯示內(nèi)存使用情況。還可以通過—s參數(shù)使用命令來不間斷地監(jiān)視內(nèi)存使用情況:
#free –b –s2
這個(gè)命令將會(huì)在終端窗口中連續(xù)不斷地報(bào)告內(nèi)存的使用情況,每2秒鐘更新一次。
(2)組合watch與 free命令用來實(shí)時(shí)監(jiān)控內(nèi)存使用情況:
代碼如下:
#watch -n 2 -d free
Every 2.0s: free Fri Jul 6 06:06:12 2007
total used free shared buffers cached
Mem: 233356 218616 14740 0 5560 64784
-/+ buffers/cache: 148272 85084
Swap: 622584 6656 615928
watch命令會(huì)每兩秒執(zhí)行 free一次,執(zhí)行前會(huì)清除屏幕,在同樣位置顯示數(shù)據(jù)。因?yàn)?watch命令不會(huì)卷動(dòng)屏幕,所以適合出長時(shí)間的監(jiān)測(cè)內(nèi)存使用率。可以使用 -n選項(xiàng),控制執(zhí)行的頻率;也可以利用 -d選項(xiàng),讓命令將每次不同的地方顯示出來。Watch命令會(huì)一直執(zhí)行,直到您按下 [Ctrl]-[C] 為止。
二、虛擬內(nèi)存的概念
(1)Linux虛擬內(nèi)存實(shí)現(xiàn)機(jī)制
Linux虛擬內(nèi)存的實(shí)現(xiàn)需要六種機(jī)制的支持:地址映射機(jī)制、內(nèi)存分配回收機(jī)制、緩存和刷新機(jī)制、請(qǐng)求頁機(jī)制、交換機(jī)制、內(nèi)存共享機(jī)制。
首先內(nèi)存管理程序通過映射機(jī)制把用戶程序的邏輯地址映射到物理地址,在用戶程序運(yùn)行時(shí)如果發(fā)現(xiàn)程序中要用的虛地址沒有對(duì)應(yīng)的物理內(nèi)存時(shí),就發(fā)出了請(qǐng)求頁要求;如果有空閑的內(nèi)存可供分配,就請(qǐng)求分配內(nèi)存(于是用到了內(nèi)存的分配和回收),并把正在使用的物理頁記錄在緩存中(使用了緩存機(jī)制)。 如果沒有足夠的內(nèi)存可供分配,那么就調(diào)用交換機(jī)制,騰出一部分內(nèi)存。另外在地址映射中要通過TLB(翻譯后援存儲(chǔ)器)來尋找物理頁;交換機(jī)制中也要用到交換緩存,并且把物理頁內(nèi)容交換到交換文件中后也要修改頁表來映射文件地址。
(2)虛擬內(nèi)存容量設(shè)定
也許有人告訴你,應(yīng)該分配2倍于物理內(nèi)存的虛擬內(nèi)存,但這是個(gè)不固定的規(guī)律。如果你的物理保存比較小,可以這樣設(shè)定。如果你有1G物理內(nèi)存或更多的話,可以縮小一下虛擬內(nèi)存。Linux會(huì)把大量的內(nèi)存用做Cache的,但在資源緊張時(shí)回收回.。你只要看到swap為0或者很小就可以放心了,因?yàn)閮?nèi)存放著不用才是最大的浪費(fèi)。
三、使甩vmstat命令監(jiān)視虛擬內(nèi)存使用情況
vmstat是Virtual Meomory Statistics(虛擬內(nèi)存統(tǒng)計(jì))的縮寫,可對(duì)操作系統(tǒng)的虛擬內(nèi)存、進(jìn)程、CPU活動(dòng)進(jìn)行監(jiān)視。它是對(duì)系統(tǒng)的整體情況進(jìn)行統(tǒng)計(jì),不足之處是無法對(duì)某個(gè)進(jìn)程進(jìn)行深入分析。通常使用vmstat 5 5(表示在5秒時(shí)間內(nèi)進(jìn)行5次采樣)命令測(cè)試。將得到一個(gè)數(shù)據(jù)匯總它可以反映真正的系統(tǒng)情況。
代碼如下:
#vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 62792 3460 9116 88092 6 30 189 89 1061 569 17 28 54 2
0 0 62792 3400 9124 88092 0 0 0 14 884 434 4 14 81 0
0 0 62792 3400 9132 88092 0 0 0 14 877 424 4 15 81 0
1 0 62792 3400 9140 88092 0 0 0 14 868 418 6 20 74 0
1 0 62792 3400 9148 88092 0 0 0 15 847 400 9 25 67 0
vmstat命令輸出分成六個(gè)部分:
(1)進(jìn)程procs:
r:在運(yùn)行隊(duì)列中等待的進(jìn)程數(shù) 。
b:在等待io的進(jìn)程數(shù) 。
(2)內(nèi)存memoy:
swpd:現(xiàn)時(shí)可用的交換內(nèi)存(單位KB)。
free:空閑的內(nèi)存(單位KB)。
buff: 緩沖去中的內(nèi)存數(shù)(單位:KB)。
cache:被用來做為高速緩存的內(nèi)存數(shù)(單位:KB)。
(3) swap交換頁面
si: 從磁盤交換到內(nèi)存的交換頁數(shù)量,單位:KB/秒。
so: 從內(nèi)存交換到磁盤的交換頁數(shù)量,單位:KB/秒。
(4) io塊設(shè)備:
bi: 發(fā)送到塊設(shè)備的塊數(shù),單位:塊/秒。
bo: 從塊設(shè)備接收到的塊數(shù),單位:塊/秒。
(5)system系統(tǒng):
in: 每秒的中斷數(shù),包括時(shí)鐘中斷。
cs: 每秒的環(huán)境(上下文)切換次數(shù)。
(6)cpu中央處理器:
cs:用戶進(jìn)程使用的時(shí)間 。以百分比表示。
sy:系統(tǒng)進(jìn)程使用的時(shí)間。 以百分比表示。
id:中央處理器的空閑時(shí)間 。以百分比表示。
如果 r經(jīng)常大于 4 ,且id經(jīng)常小于40,表示中央處理器的負(fù)荷很重。 如果bi,bo 長期不等于0,表示物理內(nèi)存容量太小。
四、Linux 服務(wù)器的內(nèi)存泄露和回收內(nèi)存的方法
1、內(nèi)存泄漏的定義:
一般我們常說的內(nèi)存泄漏是指堆內(nèi)存的泄漏。堆內(nèi)存是指程序從堆中分配的,大小任意的(內(nèi)存塊的大小可以在程序運(yùn)行期決定),使用完后必須顯示釋放的內(nèi)存。應(yīng)用程序一般使用malloc,realloc,new等函數(shù)從堆中分配到一塊內(nèi)存,使用完后,程序必須負(fù)責(zé)相應(yīng)的調(diào)用free或釋放該內(nèi)存塊,否則,這塊內(nèi)存就不能被再次使用,我們就說這塊內(nèi)存泄漏了。
2、內(nèi)存泄露的危害
從用戶使用程序的角度來看,內(nèi)存泄漏本身不會(huì)產(chǎn)生什么危害,作為一般的用戶,根本感覺不到內(nèi)存泄漏的存在。真正有危害的`是內(nèi)存泄漏的堆積,這會(huì)最終消耗盡系統(tǒng)所有的內(nèi)存。從這個(gè)角度來說,一次性內(nèi)存泄漏并沒有什么危害,因?yàn)樗粫?huì)堆積,而隱式內(nèi)存泄漏危害性則非常大,因?yàn)檩^之于常發(fā)性和偶發(fā)性內(nèi)存泄漏它更難被檢測(cè)到。存在內(nèi)存泄漏問題的程序除了會(huì)占用更多的內(nèi)存外,還會(huì)使程序的性能急劇下降。對(duì)于服務(wù)器而言,如果出現(xiàn)這種情況,即使系統(tǒng)不崩潰,也會(huì)嚴(yán)重影響使用。
3、內(nèi)存泄露的檢測(cè)和回收
對(duì)于內(nèi)存溢出之類的麻煩可能大家在編寫指針比較多的復(fù)雜的程序的時(shí)候就會(huì)遇到。在 Linux 或者 unix 下,C、C++語言是最使用工具。但是我們的 C++ 程序缺乏相應(yīng)的手段來檢測(cè)內(nèi)存信息,而只能使用 top 指令觀察進(jìn)程的動(dòng)態(tài)內(nèi)存總額。而且程序退出時(shí),我們無法獲知任何內(nèi)存泄漏信息。
使用kill命令
使用Linux命令回收內(nèi)存,我們可以使用Ps、Kill兩個(gè)命令檢測(cè)內(nèi)存使用情況和進(jìn)行回收。在使用超級(jí)用戶權(quán)限時(shí)使用命令“Ps”,它會(huì)列出所有正在運(yùn)行的程序名稱,和對(duì)應(yīng)的進(jìn)程號(hào)(PID)。Kill命令的工作原理是:向Linux操作系統(tǒng)的內(nèi)核送出一個(gè)系統(tǒng)操作信號(hào)和程序的進(jìn)程號(hào)(PID)。
應(yīng)用例子:
為了高效率回收內(nèi)存可以使用命令ps 參數(shù)v:
代碼如下:
[root@www ~]# ps v
PID TTY STAT TIME MAJFL TRS DRS RSS %MEM COMMAND
2542 tty1 Ss+ 0:00 0 8 1627 428 0.1 /sbin/mingetty tty1
2543 tty2 Ss+ 0:00 0 8 1631 428 0.1 /sbin/mingetty tty2
2547 tty3 Ss+ 0:00 0 8 1631 432 0.1 /sbin/mingetty tty3
2548 tty4 Ss+ 0:00 0 8 1627 428 0.1 /sbin/mingetty tty4
2574 tty5 Ss+ 0:00 0 8 1631 432 0.1 /sbin/mingetty tty5
2587 tty6 Ss+ 0:00 0 8 1627 424 0.1 /sbin/mingetty tty6
2657 tty7 Ss+ 1:18 12 1710 29981 7040 3.0 /usr/bin/Xorg :0 -br -a
2670 pts/2 Ss 0:01 2 682 6213 1496 0.6 -bash
3008 pts/4 Ss 0:00 2 682 6221 1472 0.6 /bin/bash
3029 pts/4 S+ 0:00 2 32 1783 548 0.2 ping 192.168.1.12
3030 pts/2 R+ 0:00 2 73 5134 768 0.3 ps v
然后如果想回收Ping命令的內(nèi)存的話,使用命令:
代碼如下:
# Kill -9 3029
使用工具軟件
Memprof是一個(gè)非常具有吸引力且非常易于使用的軟件,它由Red Hat的Owen Talyor創(chuàng)立。這個(gè)工具是用于GNOME前端的Boehm-Demers-Weiser垃圾回收器。這個(gè)工具直接就可以執(zhí)行,并且其工作起來無需對(duì)源代碼進(jìn)行任何修改。在程序執(zhí)行時(shí),這個(gè)工具會(huì)以圖形化的方式顯示內(nèi)存的使用情況。
相關(guān)介紹:Linux
嚴(yán)格來講,Linux這個(gè)詞本身只表示Linux內(nèi)核,但人們已經(jīng)習(xí)慣了用Linux來形容整個(gè)基于Linux內(nèi)核,并且使用GNU 工程各種工具和數(shù)據(jù)庫的操作系統(tǒng)。
Linux擁有以下特性:類似于Unix的基本思想,支持完全免費(fèi)與自由傳播,完全兼容POSIX1.0標(biāo)準(zhǔn),支持多用戶、多任務(wù)、有著良好的界面、支持多種平臺(tái)。Linux 能運(yùn)行主要的UNIX工具軟件、應(yīng)用程序和網(wǎng)絡(luò)協(xié)議。它支持32位和64位硬件。Linux繼承了Unix以網(wǎng)絡(luò)為核心的設(shè)計(jì)思想,是一個(gè)性能穩(wěn)定的多用戶網(wǎng)絡(luò)操作系統(tǒng)。
Linux有著許多不同的版本,但它們都使用了Linux內(nèi)核。Linux可安裝在各種計(jì)算機(jī)硬件設(shè)備中,比如手機(jī)、平板電腦、路由器、視頻游戲控制臺(tái)、臺(tái)式計(jì)算機(jī)、大型機(jī)和超級(jí)計(jì)算機(jī)。
不了解。這樣的人的第一反應(yīng)是:天啊,內(nèi)存用了好多,70個(gè)多G,可是我?guī)缀鯖]有運(yùn)行什么大程序啊?為什么會(huì)這樣?Linux好占內(nèi)存!
自以為很了解。這樣的人一般自習(xí)評(píng)估過會(huì)說:嗯,根據(jù)我專業(yè)的眼光看出來,內(nèi)存才用了17G左右,還有很多剩余內(nèi)存可用。buffers/cache占用的較多,說明系統(tǒng)中有進(jìn)程曾經(jīng)讀寫過文件,但是不要緊,這部分內(nèi)存是當(dāng)空閑來用的。
真的很了解。這種人的反應(yīng)反而讓人感覺最不懂Linux,他們的反應(yīng)是:free顯示的是這樣,好吧我知道了。神馬?你問我這些內(nèi)存夠不夠,我當(dāng)然不知道啦!我特么怎么知道你程序怎么寫的?
根據(jù)目前網(wǎng)絡(luò)上技術(shù)文檔的內(nèi)容,我相信絕大多數(shù)了解一點(diǎn)Linux的人應(yīng)該處在第二種層次。大家普遍認(rèn)為,buffers和cached所占用的內(nèi)存空間是可以在內(nèi)存壓力較大的時(shí)候被釋放當(dāng)做空閑空間用的。但真的是這樣么?在論證這個(gè)題目之前,我們先簡(jiǎn)要介紹一下buffers和cached是什么意思:
什么是buffer/cache?
buffer和cache是兩個(gè)在計(jì)算機(jī)技術(shù)中被用濫的名詞,放在不通語境下會(huì)有不同的意義。在Linux的內(nèi)存管理中,這里的buffer指Linux內(nèi)存的:Buffer cache。這里的cache指Linux內(nèi)存中的:Page cache。翻譯成中文可以叫做緩沖區(qū)緩存和頁面緩存。在歷史上,它們一個(gè)(buffer)被用來當(dāng)成對(duì)io設(shè)備寫的緩存,而另一個(gè)(cache)被用來當(dāng)作對(duì)io設(shè)備的讀緩存,這里的io設(shè)備,主要指的是塊設(shè)備文件和文件系統(tǒng)上的普通文件。但是現(xiàn)在,它們的意義已經(jīng)不一樣了。在當(dāng)前的內(nèi)核中,page cache顧名思義就是針對(duì)內(nèi)存頁的緩存,說白了就是,如果有內(nèi)存是以page進(jìn)行分配管理的,都可以使用page cache作為其緩存來管理使用。當(dāng)然,不是所有的內(nèi)存都是以頁(page)進(jìn)行管理的,也有很多是針對(duì)塊(block)進(jìn)行管理的,這部分內(nèi)存使用如果要用到cache功能,則都集中到buffer cache中來使用。(從這個(gè)角度出發(fā),是不是buffer cache改名叫做block cache更好?)然而,也不是所有塊(block)都有固定長度,系統(tǒng)上塊的長度主要是根據(jù)所使用的塊設(shè)備決定的,而頁長度在X86上無論是32位還是64位都是4k。
明白了這兩套緩存系統(tǒng)的區(qū)別,就可以理解它們究竟都可以用來做什么了。
什么是page cache
Page cache主要用來作為文件系統(tǒng)上的文件數(shù)據(jù)的緩存來用,尤其是針對(duì)當(dāng)進(jìn)程對(duì)文件有read/write操作的時(shí)候。如果你仔細(xì)想想的話,作為可以映射文件到內(nèi)存的系統(tǒng)調(diào)用:mmap是不是很自然的也應(yīng)該用到page cache?在當(dāng)前的系統(tǒng)實(shí)現(xiàn)里,page cache也被作為其它文件類型的緩存設(shè)備來用,所以事實(shí)上page cache也負(fù)責(zé)了大部分的塊設(shè)備文件的緩存工作。
什么是buffer cache
Buffer cache則主要是設(shè)計(jì)用來在系統(tǒng)對(duì)塊設(shè)備進(jìn)行讀寫的時(shí)候,對(duì)塊進(jìn)行數(shù)據(jù)緩存的系統(tǒng)來使用。這意味著某些對(duì)塊的操作會(huì)使用buffer cache進(jìn)行緩存,比如我們?cè)诟袷交募到y(tǒng)的時(shí)候。一般情況下兩個(gè)緩存系統(tǒng)是一起配合使用的,比如當(dāng)我們對(duì)一個(gè)文件進(jìn)行寫操作的時(shí)候,page cache的內(nèi)容會(huì)被改變,而buffer cache則可以用來將page標(biāo)記為不同的緩沖區(qū),并記錄是哪一個(gè)緩沖區(qū)被修改了。這樣,內(nèi)核在后續(xù)執(zhí)行臟數(shù)據(jù)的回寫(writeback)時(shí),就不用將整個(gè)page寫回,而只需要寫回修改的部分即可。
如何回收cache?
Linux內(nèi)核會(huì)在內(nèi)存將要耗盡的時(shí)候,觸發(fā)內(nèi)存回收的工作,以便釋放出內(nèi)存給急需內(nèi)存的進(jìn)程使用。一般情況下,這個(gè)操作中主要的內(nèi)存釋放都來自于對(duì)buffer/cache的釋放。尤其是被使用更多的cache空間。既然它主要用來做緩存,只是在內(nèi)存夠用的時(shí)候加快進(jìn)程對(duì)文件的讀寫速度,那么在內(nèi)存壓力較大的情況下,當(dāng)然有必要清空釋放cache,作為free空間分給相關(guān)進(jìn)程使用。所以一般情況下,我們認(rèn)為buffer/cache空間可以被釋放,這個(gè)理解是正確的。
但是這種清緩存的工作也并不是沒有成本。理解cache是干什么的就可以明白清緩存必須保證cache中的數(shù)據(jù)跟對(duì)應(yīng)文件中的數(shù)據(jù)一致,才能對(duì)cache進(jìn)行釋放。所以伴隨著cache清除的行為的,一般都是系統(tǒng)IO飆高。因?yàn)閮?nèi)核要對(duì)比cache中的數(shù)據(jù)和對(duì)應(yīng)硬盤文件上的數(shù)據(jù)是否一致,如果不一致需要寫回,之后才能回收。
在系統(tǒng)中除了內(nèi)存將被耗盡的時(shí)候可以清緩存以外,我們還可以使用下面這個(gè)文件來人工觸發(fā)緩存清除的操作:
方法是:
當(dāng)然,這個(gè)文件可以設(shè)置的值分別為1、2、3。它們所表示的含義為:
echo 1 /proc/sys/vm/drop_caches:表示清除pagecache。
echo 2 /proc/sys/vm/drop_caches:表示清除回收slab分配器中的對(duì)象(包括目錄項(xiàng)緩存和inode緩存)。slab分配器是內(nèi)核中管理內(nèi)存的一種機(jī)制,其中很多緩存數(shù)據(jù)實(shí)現(xiàn)都是用的pagecache。
echo 1 /proc/sys/vm/drop_caches:表示清除pagecache和slab分配器中的緩存對(duì)象。
cache都能被回收么?
我們分析了cache能被回收的情況,那么有沒有不能被回收的cache呢?當(dāng)然有。我們先來看第一種情況:
tmpfs
大家知道Linux提供一種“臨時(shí)”文件系統(tǒng)叫做tmpfs,它可以將內(nèi)存的一部分空間拿來當(dāng)做文件系統(tǒng)使用,使內(nèi)存空間可以當(dāng)做目錄文件來用?,F(xiàn)在絕大多數(shù)Linux系統(tǒng)都有一個(gè)叫做/dev/shm的tmpfs目錄,就是這樣一種存在。當(dāng)然,我們也可以手工創(chuàng)建一個(gè)自己的tmpfs,方法如下:
于是我們就創(chuàng)建了一個(gè)新的tmpfs,空間是20G,我們可以在/tmp/tmpfs中創(chuàng)建一個(gè)20G以內(nèi)的文件。如果我們創(chuàng)建的文件實(shí)際占用的空間是內(nèi)存的話,那么這些數(shù)據(jù)應(yīng)該占用內(nèi)存空間的什么部分呢?根據(jù)pagecache的實(shí)現(xiàn)功能可以理解,既然是某種文件系統(tǒng),那么自然該使用pagecache的空間來管理。我們?cè)囋囀遣皇沁@樣?
我們?cè)趖mpfs目錄下創(chuàng)建了一個(gè)13G的文件,并通過前后free命令的對(duì)比發(fā)現(xiàn),cached增長了13G,說明這個(gè)文件確實(shí)放在了內(nèi)存里并且內(nèi)核使用的是cache作為存儲(chǔ)。再看看我們關(guān)心的指標(biāo): -/+ buffers/cache那一行。我們發(fā)現(xiàn),在這種情況下free命令仍然提示我們有110G內(nèi)存可用,但是真的有這么多么?我們可以人工觸發(fā)內(nèi)存回收看看現(xiàn)在到底能回收多少內(nèi)存:
可以看到,cached占用的空間并沒有像我們想象的那樣完全被釋放,其中13G的空間仍然被/tmp/tmpfs中的文件占用的。當(dāng)然,我的系統(tǒng)中還有其他不可釋放的cache占用著其余16G內(nèi)存空間。那么tmpfs占用的cache空間什么時(shí)候會(huì)被釋放呢?是在其文件被刪除的時(shí)候.如果不刪除文件,無論內(nèi)存耗盡到什么程度,內(nèi)核都不會(huì)自動(dòng)幫你把tmpfs中的文件刪除來釋放cache空間。
這是我們分析的第一種cache不能被回收的情況。還有其他情況,比如:
共享內(nèi)存
共享內(nèi)存是系統(tǒng)提供給我們的一種常用的進(jìn)程間通信(IPC)方式,但是這種通信方式不能在shell中申請(qǐng)和使用,所以我們需要一個(gè)簡(jiǎn)單的測(cè)試程序,代碼如下:
程序功能很簡(jiǎn)單,就是申請(qǐng)一段不到2G共享內(nèi)存,然后打開一個(gè)子進(jìn)程對(duì)這段共享內(nèi)存做一個(gè)初始化操作,父進(jìn)程等子進(jìn)程初始化完之后輸出一下共享內(nèi)存的內(nèi)容,然后退出。但是退出之前并沒有刪除這段共享內(nèi)存。我們來看看這個(gè)程序執(zhí)行前后的內(nèi)存使用:
cached空間由16G漲到了18G。那么這段cache能被回收么?繼續(xù)測(cè)試:
結(jié)果是仍然不可回收。大家可以觀察到,這段共享內(nèi)存即使沒人使用,仍然會(huì)長期存放在cache中,直到其被刪除。刪除方法有兩種,一種是程序中使用shmdt(),另一種是使用ipcrm命令。我們來刪除試試:
刪除共享內(nèi)存后,cache被正常釋放了。這個(gè)行為與tmpfs的邏輯類似。內(nèi)核底層在實(shí)現(xiàn)共享內(nèi)存(shm)、消息隊(duì)列(msg)和信號(hào)量數(shù)組(sem)這些POSIX:XSI的IPC機(jī)制的內(nèi)存存儲(chǔ)時(shí),使用的都是tmpfs。這也是為什么共享內(nèi)存的操作邏輯與tmpfs類似的原因。當(dāng)然,一般情況下是shm占用的內(nèi)存更多,所以我們?cè)诖酥攸c(diǎn)強(qiáng)調(diào)共享內(nèi)存的使用。說到共享內(nèi)存,Linux還給我們提供了另外一種共享內(nèi)存的方法,就是:
mmap
mmap()是一個(gè)非常重要的系統(tǒng)調(diào)用,這僅從mmap本身的功能描述上是看不出來的。從字面上看,mmap就是將一個(gè)文件映射進(jìn)進(jìn)程的虛擬內(nèi)存地址,之后就可以通過操作內(nèi)存的方式對(duì)文件的內(nèi)容進(jìn)行操作。但是實(shí)際上這個(gè)調(diào)用的用途是很廣泛的。當(dāng)malloc申請(qǐng)內(nèi)存時(shí),小段內(nèi)存內(nèi)核使用sbrk處理,而大段內(nèi)存就會(huì)使用mmap。當(dāng)系統(tǒng)調(diào)用exec族函數(shù)執(zhí)行時(shí),因?yàn)槠浔举|(zhì)上是將一個(gè)可執(zhí)行文件加載到內(nèi)存執(zhí)行,所以內(nèi)核很自然的就可以使用mmap方式進(jìn)行處理。我們?cè)诖藘H僅考慮一種情況,就是使用mmap進(jìn)行共享內(nèi)存的申請(qǐng)時(shí),會(huì)不會(huì)跟shmget()一樣也使用cache?
同樣,我們也需要一個(gè)簡(jiǎn)單的測(cè)試程序:
這次我們干脆不用什么父子進(jìn)程的方式了,就一個(gè)進(jìn)程,申請(qǐng)一段2G的mmap共享內(nèi)存,然后初始化這段空間之后等待100秒,再解除影射所以我們需要在它sleep這100秒內(nèi)檢查我們的系統(tǒng)內(nèi)存使用,看看它用的是什么空間?當(dāng)然在這之前要先創(chuàng)建一個(gè)2G的文件./mmapfile。結(jié)果如下:
然后執(zhí)行測(cè)試程序:
我們可以看到,在程序執(zhí)行期間,cached一直為18G,比之前漲了2G,并且此時(shí)這段cache仍然無法被回收。然后我們等待100秒之后程序結(jié)束。
程序退出之后,cached占用的空間被釋放。這樣我們可以看到,使用mmap申請(qǐng)標(biāo)志狀態(tài)為MAP_SHARED的內(nèi)存,內(nèi)核也是使用的cache進(jìn)行存儲(chǔ)的。在進(jìn)程對(duì)相關(guān)內(nèi)存沒有釋放之前,這段cache也是不能被正常釋放的。實(shí)際上,mmap的MAP_SHARED方??申請(qǐng)的內(nèi)存,在內(nèi)核中也是由tmpfs實(shí)現(xiàn)的。由此我們也可以推測(cè),由于共享庫的只讀部分在內(nèi)存中都是以mmap的MAP_SHARED方式進(jìn)行管理,實(shí)際上它們也都是要占用cache且無法被釋放的。
最后
我們通過三個(gè)測(cè)試?yán)?,發(fā)現(xiàn)Linux系統(tǒng)內(nèi)存中的cache并不是在所有情況下都能被釋放當(dāng)做空閑空間用的。并且也也明確了,即使可以釋放cache,也并不是對(duì)系統(tǒng)來說沒有成本的??偨Y(jié)一下要點(diǎn),我們應(yīng)該記得這樣幾點(diǎn):
當(dāng)cache作為文件緩存被釋放的時(shí)候會(huì)引發(fā)IO變高,這是cache加快文件訪問速度所要付出的成本。
tmpfs中存儲(chǔ)的文件會(huì)占用cache空間,除非文件刪除否則這個(gè)cache不會(huì)被自動(dòng)釋放。
使用shmget方式申請(qǐng)的共享內(nèi)存會(huì)占用cache空間,除非共享內(nèi)存被ipcrm或者shmdt,否則相關(guān)的cache空間都不會(huì)被自動(dòng)釋放。
使用mmap方法申請(qǐng)的MAP_SHARED標(biāo)志的內(nèi)存會(huì)占用cache空間,除非進(jìn)程將這段內(nèi)存munmap,否則相關(guān)的cache空間都不會(huì)被自動(dòng)釋放。
實(shí)際上shmget、mmap的共享內(nèi)存,在內(nèi)核層都是通過tmpfs實(shí)現(xiàn)的,tmpfs實(shí)現(xiàn)的存儲(chǔ)用的都是cache。