有了上一篇關於pids的熱身以後,咱們這篇將介紹稍微複雜點的內存控制。html
本篇全部例子都在ubuntu-server-x86_64 16.04下執行經過node
代碼總會有bug,有時會有內存泄漏,或者有意想不到的內存分配狀況,或者這是個惡意程序,運行起來就是爲了榨乾系統內存,讓其它進程沒法分配到足夠的內存而出現異常,若是系統配置了交換分區,會致使系統大量使用交換分區,從而系統運行很慢。linux
站在一個普通Linux開發者的角度,若是能控制一個或者一組進程所能使用的內存數,那麼就算代碼有bug,內存泄漏也不會對系統形成影響,由於能夠設置內存使用量的上限,當到達這個值以後能夠將進程重啓。web
站在一個系統管理者的角度,若是能限制每組進程所能使用的內存量,那麼無論程序的質量如何,都能將它們對系統的影響降到最低,從而保證整個系統的穩定性。shell
限制cgroup中全部進程所能使用的物理內存總量ubuntu
限制cgroup中全部進程所能使用的物理內存+交換空間總量(CONFIG_MEMCG_SWAP): 通常在server上,不太會用到swap空間,因此不在這裏介紹這部份內容。segmentfault
限制cgroup中全部進程所能使用的內核內存總量及其它一些內核資源(CONFIG_MEMCG_KMEM): 限制內核內存有什麼用呢?其實限制內核內存就是限制當前cgroup所能使用的內核資源,好比進程的內核棧空間,socket所佔用的內存空間等,經過限制內核內存,當內存吃緊時,能夠阻止當前cgroup繼續建立進程以及向內核申請分配更多的內核資源。因爲這塊功能被使用的較少,本篇中也不對它作介紹。bash
因爲memory subsystem比較耗資源,因此內核專門添加了一個參數cgroup_disable=memory來禁用整個memory subsystem,這個參數能夠經過GRUB在啓動系統的時候傳給內核,加了這個參數後內核將再也不進行memory subsystem相關的計算工做,在系統中也不能掛載memory subsystem。app
上面提到的CONFIG_MEMCG_SWAP和CONFIG_MEMCG_KMEM都是擴展功能,在使用前請確認當前內核是否支持,下面看看ubuntu 16.04的內核:socket
#這裏CONFIG_MEMCG_SWAP和CONFIG_MEMCG_KMEM等於y表示內核已經編譯了該模塊,即支持相關功能 dev@dev:~$ cat /boot/config-`uname -r`|grep CONFIG_MEMCG CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y # CONFIG_MEMCG_SWAP_ENABLED is not set CONFIG_MEMCG_KMEM=y
CONFIG_MEMCG_SWAP控制內核是否支持Swap Extension,而CONFIG_MEMCG_SWAP_ENABLED(3.6之後的內核新加的參數)控制默認狀況下是否使用Swap Extension,因爲Swap Extension比較耗資源,因此不少發行版(好比ubuntu)默認狀況下會禁用該功能(這也是上面那行被註釋掉的緣由),固然用戶也能夠根據實際狀況,經過設置內核參數swapaccount=0或者1來手動禁用和啓用Swap Extension。
在ubuntu 16.04裏面,systemd已經幫咱們將memory綁定到了/sys/fs/cgroup/memory
#若是這裏發現有多行結果,說明這顆cgroup數被綁定到了多個地方, #不過不要擔憂,因爲它們都是指向同一顆cgroup樹,因此它們裏面的內容是如出一轍的 dev@dev:~$ mount|grep memory cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
在/sys/fs/cgroup/memory下建立一個子目錄即建立了一個子cgroup
#--------------------------第一個shell窗口---------------------- dev@dev:~$ cd /sys/fs/cgroup/memory dev@dev:/sys/fs/cgroup/memory$ sudo mkdir test dev@dev:/sys/fs/cgroup/memory$ ls test cgroup.clone_children memory.kmem.failcnt memory.kmem.tcp.limit_in_bytes memory.max_usage_in_bytes memory.soft_limit_in_bytes notify_on_release cgroup.event_control memory.kmem.limit_in_bytes memory.kmem.tcp.max_usage_in_bytes memory.move_charge_at_immigrate memory.stat tasks cgroup.procs memory.kmem.max_usage_in_bytes memory.kmem.tcp.usage_in_bytes memory.numa_stat memory.swappiness memory.failcnt memory.kmem.slabinfo memory.kmem.usage_in_bytes memory.oom_control memory.usage_in_bytes memory.force_empty memory.kmem.tcp.failcnt memory.limit_in_bytes memory.pressure_level memory.use_hierarchy
從上面ls的輸出能夠看出,除了每一個cgroup都有的那幾個文件外,和memory相關的文件還很多(因爲ubuntu默認禁用了CONFIG_MEMCG_SWAP,因此這裏看不到swap相關的文件),這裏先作個大概介紹(kernel相關的文件除外),後面會詳細介紹每一個文件的做用
cgroup.event_control #用於eventfd的接口 memory.usage_in_bytes #顯示當前已用的內存 memory.limit_in_bytes #設置/顯示當前限制的內存額度 memory.failcnt #顯示內存使用量達到限制值的次數 memory.max_usage_in_bytes #歷史內存最大使用量 memory.soft_limit_in_bytes #設置/顯示當前限制的內存軟額度 memory.stat #顯示當前cgroup的內存使用狀況 memory.use_hierarchy #設置/顯示是否將子cgroup的內存使用狀況統計到當前cgroup裏面 memory.force_empty #觸發系統當即儘量的回收當前cgroup中能夠回收的內存 memory.pressure_level #設置內存壓力的通知事件,配合cgroup.event_control一塊兒使用 memory.swappiness #設置和顯示當前的swappiness memory.move_charge_at_immigrate #設置當進程移動到其餘cgroup中時,它所佔用的內存是否也隨着移動過去 memory.oom_control #設置/顯示oom controls相關的配置 memory.numa_stat #顯示numa相關的內存
和「建立並管理cgroup」中介紹的同樣,往cgroup中添加進程只要將進程號寫入cgroup.procs就能夠了
注意:本篇將以進程爲單位進行操做,不考慮以線程爲單位進行管理(緣由見「建立並管理cgroup」中cgroup.pro與tasks的區別),也即只寫cgroup.procs文件,不會寫tasks文件
#--------------------------第二個shell窗口---------------------- #從新打開一個shell窗口,避免相互影響 dev@dev:~$ cd /sys/fs/cgroup/memory/test/ dev@dev:/sys/fs/cgroup/memory/test$ echo $$ 4589 dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo $$ >> cgroup.procs" #運行top命令,這樣這個cgroup消耗的內存會多點,便於觀察 dev@dev:/sys/fs/cgroup/memory/test$ top #後續操做再也不在這個窗口進行,避免在這個bash中運行進程影響cgropu裏面的進程數及相關統計
設置限額很簡單,寫文件memory.limit_in_bytes就能夠了,請仔細看示例
#--------------------------第一個shell窗口---------------------- #回到第一個shell窗口 dev@dev:/sys/fs/cgroup/memory$ cd test #這裏兩個進程id分別時第二個窗口的bash和top進程 dev@dev:/sys/fs/cgroup/memory/test$ cat cgroup.procs 4589 4664 #開始設置以前,看看當前使用的內存數量,這裏的單位是字節 dev@dev:/sys/fs/cgroup/memory/test$ cat memory.usage_in_bytes 835584 #設置1M的限額 dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo 1M > memory.limit_in_bytes" #設置完以後記得要查看一下這個文件,由於內核要考慮頁對齊, 因此生效的數量不必定徹底等於設置的數量 dev@dev:/sys/fs/cgroup/memory/test$ cat memory.limit_in_bytes 1048576 #若是再也不須要限制這個cgroup,寫-1到文件memory.limit_in_bytes便可 dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo -1 > memory.limit_in_bytes" #這時能夠看到limit被設置成了一個很大的數字 dev@dev:/sys/fs/cgroup/memory/test$ cat memory.limit_in_bytes 9223372036854771712
若是設置的限額比當前已經使用的內存少呢?如上面顯示當前bash用了800多k,若是我設置limit爲400K會怎麼樣?
#--------------------------第一個shell窗口---------------------- #先用free看下當前swap被用了多少 dev@dev:/sys/fs/cgroup/memory/test$ free total used free shared buff/cache available Mem: 500192 45000 34200 2644 420992 424020 Swap: 524284 16 524268 #設置內存限額爲400K dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo 400K > memory.limit_in_bytes" #再看當前cgroup的內存使用狀況 #發現內存佔用少了不少,恰好在400K之內,原來用的那些內存都去哪了呢? dev@dev:/sys/fs/cgroup/memory/test$ cat memory.usage_in_bytes 401408 #再看swap空間的佔用狀況,和剛開始比,多了500-16=384K,說明內存中的數據被移到了swap上 dev@dev:/sys/fs/cgroup/memory/test$ free total used free shared buff/cache available Mem: 500192 43324 35132 2644 421736 425688 Swap: 524284 500 523784 #這個時候再來看failcnt,發現有453次之多(隔幾秒再看這個文件,發現次數在增加) dev@dev:/sys/fs/cgroup/memory/test$ cat memory.failcnt 453 #再看看memory.stat(這裏只顯示部份內容),發現物理內存用了400K, #但有不少pgmajfault以及pgpgin和pgpgout,說明發生了不少的swap in和swap out dev@dev:/sys/fs/cgroup/memory/test$ cat memory.stat rss 409600 total_pgpgin 4166 total_pgpgout 4066 total_pgfault 7558 total_pgmajfault 419 #從上面的結果能夠看出,當物理內存不夠時,就會觸發memory.failcnt裏面的數量加1, #但進程不會被kill掉,那是由於內核會嘗試將物理內存中的數據移動到swap空間中,從而讓內存分配成功
若是設置的限額太小,就算swap out部份內存後仍是不夠會怎麼樣?
#--------------------------第一個shell窗口---------------------- dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo 1K > memory.limit_in_bytes" #進程已經不在了(第二個窗口已經掛掉了) dev@dev:/sys/fs/cgroup/memory/test$ cat cgroup.procs dev@dev:/sys/fs/cgroup/memory/test$ cat memory.usage_in_bytes 0 #從這裏的結果能夠看出,第二個窗口的bash和top都被kill掉了
從上面的這些測試能夠看出,一旦設置了內存限制,將當即生效,而且當物理內存使用量達到limit的時候,memory.failcnt的內容會加1,但這時進程不必定就會被kill掉,內核會盡可能將物理內存中的數據移到swap空間上去,若是實在是沒辦法移動了(設置的limit太小,或者swap空間不足),默認狀況下,就會kill掉cgroup裏面繼續申請內存的進程。
當物理內存達到上限後,系統的默認行爲是kill掉cgroup中繼續申請內存的進程,那麼怎麼控制這樣的行爲呢?答案是配置memory.oom_control
這個文件裏面包含了一個控制是否爲當前cgroup啓動OOM-killer的標識。若是寫0到這個文件,將啓動OOM-killer,當內核沒法給進程分配足夠的內存時,將會直接kill掉該進程;若是寫1到這個文件,表示不啓動OOM-killer,當內核沒法給進程分配足夠的內存時,將會暫停該進程直到有空餘的內存以後再繼續運行;同時,memory.oom_control還包含一個只讀的under_oom字段,用來表示當前是否已經進入oom狀態,也便是否有進程被暫停了。
注意:root cgroup的oom killer是不能被禁用的
爲了演示OOM-killer的功能,建立了下面這樣一個程序,用來向系統申請內存,它會每秒消耗1M的內存。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define MB (1024 * 1024) int main(int argc, char *argv[]) { char *p; int i = 0; while(1) { p = (char *)malloc(MB); memset(p, 0, MB); printf("%dM memory allocated\n", ++i); sleep(1); } return 0; }
保存上面的程序到文件~/mem-allocate.c,而後編譯並測試
#--------------------------第一個shell窗口---------------------- #編譯上面的文件 dev@dev:/sys/fs/cgroup/memory/test$ gcc ~/mem-allocate.c -o ~/mem-allocate #設置內存限額爲5M dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo 5M > memory.limit_in_bytes" #將當前bash加入到test中,這樣這個bash建立的全部進程都會自動加入到test中 dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo $$ >> cgroup.procs" #默認狀況下,memory.oom_control的值爲0,即默認啓用oom killer dev@dev:/sys/fs/cgroup/memory/test$ cat memory.oom_control oom_kill_disable 0 under_oom 0 #爲了不受swap空間的影響,設置swappiness爲0來禁止當前cgroup使用swap dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo 0 > memory.swappiness" #當分配第5M內存時,因爲總內存量超過了5M,因此進程被kill了 dev@dev:/sys/fs/cgroup/memory/test$ ~/mem-allocate 1M memory allocated 2M memory allocated 3M memory allocated 4M memory allocated Killed #設置oom_control爲1,這樣內存達到限額的時候會暫停 dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo 1 >> memory.oom_control" #跟預期的同樣,程序被暫停了 dev@dev:/sys/fs/cgroup/memory/test$ ~/mem-allocate 1M memory allocated 2M memory allocated 3M memory allocated 4M memory allocated #--------------------------第二個shell窗口---------------------- #再打開一個窗口 dev@dev:~$ cd /sys/fs/cgroup/memory/test/ #這時候能夠看到memory.oom_control裏面under_oom的值爲1,表示當前已經oom了 dev@dev:/sys/fs/cgroup/memory/test$ cat memory.oom_control oom_kill_disable 1 under_oom 1 #修改test的額度爲7M dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo 7M > memory.limit_in_bytes" #--------------------------第一個shell窗口---------------------- #再回到第一個窗口,會發現進程mem-allocate繼續執行了兩步,而後暫停在6M那裏了 dev@dev:/sys/fs/cgroup/memory/test$ ~/mem-allocate 1M memory allocated 2M memory allocated 3M memory allocated 4M memory allocated 5M memory allocated 6M memory allocated
該文件還能夠配合cgroup.event_control實現OOM的通知,當OOM發生時,能夠收到相關的事件,下面是用於測試的程序,流程大概以下:
利用函數eventfd()建立一個efd;
打開文件memory.oom_control,獲得ofd;
往cgroup.event_control中寫入這麼一串:<efd> <ofd>
經過讀efd獲得通知,而後打印一句話到終端
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/eventfd.h> #include <errno.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> static inline void die(const char *msg) { fprintf(stderr, "error: %s: %s(%d)\n", msg, strerror(errno), errno); exit(EXIT_FAILURE); } #define BUFSIZE 256 int main(int argc, char *argv[]) { char buf[BUFSIZE]; int efd, cfd, ofd; uint64_t u; if ((efd = eventfd(0, 0)) == -1) die("eventfd"); snprintf(buf, BUFSIZE, "%s/%s", argv[1], "cgroup.event_control"); if ((cfd = open(buf, O_WRONLY)) == -1) die("cgroup.event_control"); snprintf(buf, BUFSIZE, "%s/%s", argv[1], "memory.oom_control"); if ((ofd = open(buf, O_RDONLY)) == -1) die("memory.oom_control"); snprintf(buf, BUFSIZE, "%d %d", efd, ofd); if (write(cfd, buf, strlen(buf)) == -1) die("write cgroup.event_control"); if (close(cfd) == -1) die("close cgroup.event_control"); for (;;) { if (read(efd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) die("read eventfd"); printf("mem_cgroup oom event received\n"); } return 0; }
將上面的文件保存爲~/oom_listen.c,而後測試以下
#--------------------------第二個shell窗口---------------------- #編譯程序 dev@dev:/sys/fs/cgroup/memory/test$ gcc ~/oom_listen.c -o ~/oom_listen #啓用oom killer dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo 0 >> memory.oom_control" #設置限額爲2M,縮短測試周期 dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo 2M > memory.limit_in_bytes" #啓動監聽程序 dev@dev:/sys/fs/cgroup/memory/test$ ~/oom_listen /sys/fs/cgroup/memory/test #--------------------------第一個shell窗口---------------------- #連續運行兩次mem-allocate,使它觸發oom killer dev@dev:/sys/fs/cgroup/memory/test$ ~/mem-allocate 1M memory allocated Killed dev@dev:/sys/fs/cgroup/memory/test$ ~/mem-allocate 1M memory allocated Killed #--------------------------第二個shell窗口---------------------- #回到第二個窗口能夠看到,收到了兩次oom事件 dev@dev:/sys/fs/cgroup/memory/test$ ~/oom_listen /sys/fs/cgroup/memory/test mem_cgroup oom event received mem_cgroup oom event received
當一個進程從一個cgroup移動到另外一個cgroup時,默認狀況下,該進程已經佔用的內存仍是統計在原來的cgroup裏面,不會佔用新cgroup的配額,但新分配的內存會統計到新的cgroup中(包括swap out到交換空間後再swap in到物理內存中的部分)。
咱們能夠經過設置memory.move_charge_at_immigrate讓進程所佔用的內存隨着進程的遷移一塊兒遷移到新的cgroup中。
enable: echo 1 > memory.move_charge_at_immigrate disable:echo 0 > memory.move_charge_at_immigrate
注意: 就算設置爲1,但若是不是thread group的leader,這個task佔用的內存也不能被遷移過去。換句話說,若是以線程爲單位進行遷移,必須是進程的第一個線程,若是以進程爲單位進行遷移,就沒有這個問題。
當memory.move_charge_at_immigrate被設置成1以後,進程佔用的內存將會被統計到目的cgroup中,若是目的cgroup沒有足夠的內存,系統將嘗試回收目的cgroup的部份內存(和系統內存緊張時的機制同樣,刪除不經常使用的file backed的內存或者swap out到交換空間上,請參考Linux內存管理),若是回收不成功,那麼進程遷移將失敗。
注意:遷移內存佔用數據是比較耗時的操做。
當memory.move_charge_at_immigrate爲0時,就算當前cgroup中裏面的進程都已經移動到其它cgropu中去了,因爲進程已經佔用的內存沒有被統計過去,當前cgroup有可能還佔用不少內存,當移除該cgroup時,佔用的內存須要統計到誰頭上呢?答案是依賴memory.use_hierarchy的值,若是該值爲0,將會統計到root cgroup裏;若是值爲1,將統計到它的父cgroup裏面。
當向memory.force_empty文件寫入0時(echo 0 > memory.force_empty),將會當即觸發系統儘量的回收該cgroup佔用的內存。該功能主要使用場景是移除cgroup前(cgroup中沒有進程),先執行該命令,能夠儘量的回收該cgropu佔用的內存,這樣遷移內存的佔用數據到父cgroup或者root cgroup時會快些。
該文件的值默認和全局的swappiness(/proc/sys/vm/swappiness)同樣,修改該文件只對當前cgroup生效,其功能和全局的swappiness同樣,請參考Linux交換空間中關於swappiness的介紹。
注意:有一點和全局的swappiness不一樣,那就是若是這個文件被設置成0,就算系統配置的有交換空間,當前cgroup也不會使用交換空間。
該文件內容爲0時,表示不使用繼承,即父子cgroup之間沒有關係;當該文件內容爲1時,子cgroup所佔用的內存會統計到全部祖先cgroup中。
若是該文件內容爲1,當一個cgroup內存吃緊時,會觸發系統回收它以及它全部子孫cgroup的內存。
注意: 當該cgroup下面有子cgroup或者父cgroup已經將該文件設置成了1,那麼當前cgroup中的該文件就不能被修改。
#當前cgroup和父cgroup裏都是1 dev@dev:/sys/fs/cgroup/memory/test$ cat memory.use_hierarchy 1 dev@dev:/sys/fs/cgroup/memory/test$ cat ../memory.use_hierarchy 1 #因爲父cgroup裏面的值爲1,因此修改當前cgroup的值失敗 dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo 0 > ./memory.use_hierarchy" sh: echo: I/O error #因爲父cgroup裏面有子cgroup(至少有當前cgroup這麼一個子cgroup), #修改父cgroup裏面的值也失敗 dev@dev:/sys/fs/cgroup/memory/test$ sudo sh -c "echo 0 > ../memory.use_hierarchy" sh: echo: I/O error
有了hard limit(memory.limit_in_bytes),爲何還要soft limit呢?hard limit是一個硬性標準,絕對不能超過這個值,而soft limit能夠被超越,既然能被超越,要這個配置還有啥用?先看看它的特色
當系統內存充裕時,soft limit不起任何做用
當系統內存吃緊時,系統會盡可能的將cgroup的內存限制在soft limit值之下(內核會盡可能,但不100%保證)
從它的特色能夠看出,它的做用主要發生在系統內存吃緊時,若是沒有soft limit,那麼全部的cgroup一塊兒競爭內存資源,佔用內存多的cgroup不會讓着內存佔用少的cgroup,這樣就會出現某些cgroup內存飢餓的狀況。若是配置了soft limit,那麼當系統內存吃緊時,系統會讓超過soft limit的cgroup釋放出超過soft limit的那部份內存(有可能更多),這樣其它cgroup就有了更多的機會分配到內存。
從上面的分析看出,這實際上是系統內存不足時的一種妥協機制,給次等重要的進程設置soft limit,當系統內存吃緊時,把機會讓給其它重要的進程。
注意: 當系統內存吃緊且cgroup達到soft limit時,系統爲了把當前cgroup的內存使用量控制在soft limit下,在收到當前cgroup新的內存分配請求時,就會觸發回收內存操做,因此一旦到達這個狀態,就會頻繁的觸發對當前cgroup的內存回收操做,會嚴重影響當前cgroup的性能。
這個文件主要用來監控當前cgroup的內存壓力,當內存壓力大時(即已使用內存快達到設置的限額),在分配內存以前須要先回收部份內存,從而影響內存分配速度,影響性能,而經過監控當前cgroup的內存壓力,能夠在有壓力的時候採起必定的行動來改善當前cgroup的性能,好比關閉當前cgroup中不重要的服務等。目前有三種壓力水平:
意味着系統在開始爲當前cgroup分配內存以前,須要先回收內存中的數據了,這時候回收的是在磁盤上有對應文件的內存數據。
意味着系統已經開始頻繁爲當前cgroup使用交換空間了。
快撐不住了,系統隨時有可能kill掉cgroup中的進程。
如何配置相關的監聽事件呢?和memory.oom_control相似,大概步驟以下:
利用函數eventfd(2)建立一個event_fd
打開文件memory.pressure_level,獲得pressure_level_fd
往cgroup.event_control中寫入這麼一串:<event_fd> <pressure_level_fd> <level>
而後經過讀event_fd獲得通知
注意: 多個level可能要建立多個event_fd,好像沒有辦法共用一個(本人沒有測試過)
咱們能夠經過cgroup的事件通知機制來實現對內存的監控,當內存使用量穿過(變得高於或者低於)咱們設置的值時,就會收到通知。使用方法和memory.oom_control相似,大概步驟以下:
利用函數eventfd(2)建立一個event_fd
打開文件memory.usage_in_bytes,獲得usage_in_bytes_fd
往cgroup.event_control中寫入這麼一串:<event_fd> <usage_in_bytes_fd> <threshold>
而後經過讀event_fd獲得通知
這個文件包含的統計項比較細,須要一些內核的內存管理知識才能看懂,這裏就不介紹了(怕說錯)。詳細信息能夠參考Memory Resource Controller中的「5.2 stat file」。這裏有幾個須要注意的地方:
裏面total開頭的統計項包含了子cgroup的數據(前提條件是memory.use_hierarchy等於1)。
裏面的'rss + file_mapped"才約等因而咱們常說的RSS(ps aux命令看到的RSS)
文件(動態庫和可執行文件)及共享內存能夠在多個進程之間共享,不過它們只會統計到他們的owner cgroup中的file_mapped去。(不肯定是怎麼定義owner的,但若是看到當前cgroup的file_mapped值很小,說明共享的數據沒有算到它頭上,而是其它的cgroup)
本篇沒有介紹swap和kernel相關的內容,不過在實際使用過程當中必定要留意swap空間,若是系統使用了交換空間,那麼設置限額時必定要注意一點,那就是當cgroup的物理空間不夠時,內核會將不經常使用的內存swap out到交換空間上,從而致使一直不觸發oom killer,而是不停的swap out/in,致使cgroup中的進程運行速度很慢。若是必定要用交換空間,最好的辦法是限制swap+物理內存的額度,雖然咱們在這篇中沒有介紹這部份內容,但其使用方法和限制物理內存是同樣的,只是換作寫文件memory.memsw.limit_in_bytes罷了。