1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Linux Used內存到底哪里去了?

        共 5498字,需瀏覽 11分鐘

         ·

        2020-08-17 19:33


        點擊「閱讀原文」查看良許原創(chuàng)精品視頻。

        來自:系統(tǒng)技術非業(yè)余研究

        作者:Yu Feng

        鏈接:http://blog.yufeng.info/archives/245

        前幾天小馬同學問了一個問題:
        我ps aux看到的RSS內存只有不到30M,但是free看到內存卻已經使用了7,8G了,已經開始swap了,請問ps aux的實際物理內存統(tǒng)計是不是漏了哪些內存沒算?我有什么辦法確定free中used的內存都去哪兒了呢?
        這個問題不止一個同學遇到過了,之前小王同學也遇到這個問題,內存的計算總是一個迷糊賬。我們今天來把它算個清楚下!
        通常我們是這樣看內存的剩余情況的:
        $free?-m
        ?????????????total???????used???????free?????shared????buffers?????cached
        Mem:?????????48262???????7913??????40349??????????0?????????14????????267
        -/+?buffers/cache:???????7631??????40631
        Swap:?????????2047????????336???????1711


        那么這個信息是如何解讀的呢,以下這個圖解釋的挺清楚的!
        上面的情況下我們總的內存有48262M,用掉了7913M。其中buffer+cache總共14+267=281M, 由于這種類型的內存是可以回收的,雖然我們用掉了7913M,但是實際上我們如果實在需要的話,這部分buffer/cache內存是可以放出來的。
        我們來演示下:
        $?sudo?sysctl?vm.drop_caches=3
        vm.drop_caches?=?3
        $?free?-m
        ?????????????total???????used???????free?????shared????buffers?????cached
        Mem:?????????48262???????7676??????40586??????????0??????????3?????????41
        -/+?buffers/cache:???????7631??????40631
        Swap:?????????2047????????336???????1711


        我們把buffer/cache大部分都清除干凈了,只用了44M,所以我們這次used的空間是7676M。
        到現(xiàn)在我們比較清楚幾個概念:
        1. 總的內存多少
        2. buffer/cache內存可以釋放的。
        3. used的內存的概率。
        即使是這樣我們還是要繼續(xù)追查下used的空間(7637M)到底用到哪里去了?
        這里首先我們來介紹下nmon這個工具,它對內存的使用顯示比較直觀。
        使用的內存的去向我們很自然的就想到操作系統(tǒng)系統(tǒng)上的各種進程需要消耗各種內存,我們透過top工具來看下:
        通常我們會看進程的RES這一項,這項到底是什么意思呢?這個數(shù)字從哪里出來的呢?通過strace對top和nmon的追蹤和結合源碼,我們確定這個值是從/proc/PID/statm的第二個字段讀取出來的.
        那這個字段什么意思呢?
        man proc
        或者http://www.kernel.org/doc/man-pages/online/pages/man5/proc.5.html 會詳細的解釋/proc/下的文件的具體意思,我們摘抄下:
        /proc/[pid]/statm
        Provides?information?about?memory?usage,?measured?in?pages.?The
        columns?are:

        size?total?program?size
        (same?as?VmSize?in?/proc/[pid]/status)
        resident?resident?set?size
        (same?as?VmRSS?in?/proc/[pid]/status)
        share?shared?pages?(from?shared?mappings)
        text?text?(code)
        lib?library?(unused?in?Linux?2.6)
        data?data?+?stack
        dt?dirty?pages?(unused?in?Linux?2.6)

        resident set size 也就是每個進程用了具體的多少頁的內存。由于linux系統(tǒng)采用的是虛擬內存,進程的代碼,庫,堆和棧使用的內存都會消耗內存,但是申請出來的內存,只要沒真正touch過,是不算的,因為沒有真正為之分配物理頁面。
        我們實際進程使用的物理頁面應該用resident set size來算的,遍歷所有的進程,就可以知道所有的所有的進程使用的內存。
        我們來實驗下RSS的使用情況:
        $?cat?RSS.sh
        #/bin/bash???????????????????????????????????????????????????????????????????????????????????????????????????????????????
        for?PROC?in?`ls??/proc/|grep?"^[0-9]"`
        do
        ??if?[?-f?/proc/$PROC/statm?];?then
        ??????TEP=`cat?/proc/$PROC/statm?|?awk?'{print?($2)}'`
        ??????RSS=`expr?$RSS?+?$TEP`
        ??fi
        done
        RSS=`expr?$RSS?\*?4`
        echo?$RSS"KB"
        $?./RSS.sh??
        7024692KB


        從數(shù)字來看,我們的進程使用了大概7024M內存,距離7637M還有幾百M內存哪里去了?哪里去了?貓吃掉了?
        我們再回頭來仔細看下nmon的內存統(tǒng)計表。
        那個該死的slab是什么呢?那個PageTables又是什么呢?
        簡單的說內核為了高性能每個需要重復使用的對象都會有個池,這個slab池會cache大量常用的對象,所以會消耗大量的內存。運行命令:
        $?slabtop


        我們可以看到


        從圖我們可以看出各種對象的大小和數(shù)目,遺憾的是沒有告訴我們slab消耗了多少內存。
        我們自己來算下好了:
        $?echo?`cat?/proc/slabinfo?|awk?'BEGIN{sum=0;}{sum=sum+$3*$4;}END{print?sum/1024/1024}'`?MB
        904.256?MB


        好吧,把每個對象的數(shù)目*大小,再累加,我們就得到了總的內存消耗量:904M
        那么PageTables呢?我們萬能的內核組的同學現(xiàn)身了:


        伯瑜:
        你還沒有計算page?tables的大小,還有struct?page也有一定的大?。總€頁一個,64bytes),如果是2.6.32的話,每個頁還有一個page_cgroup(32bytes),也就是說內存大小的2.3%(96/4096)會被內核固定使用的
        含黛:

        struct?page是系統(tǒng)boot的時候就會根據(jù)內存大小算出來分配出去的,18內核是1.56%左右,32內核由于cgroup的原因會在2.3%


        好吧,知道是干嘛的啦,管理這些物理頁面的硬開銷,那么具體是多少呢?
        $?echo?`grep?PageTables?/proc/meminfo?|?awk?'{print?$2}'`?KB
        58052?KB


        好吧,小結下!內存的去向主要有3個:


        • 1. 進程消耗。
        • 2. slab消耗?
        • 3.pagetable消耗。
        我把三種消耗匯總下和free出的結果比對下,這個腳本的各種計算項仲同學幫忙搞定的:


        $?cat?cm.sh
        #/bin/bash
        for?PROC?in?`ls?/proc/|grep?"^[0-9]"`
        do
        ??if?[?-f?/proc/$PROC/statm?];?then
        ??????TEP=`cat?/proc/$PROC/statm?|?awk?'{print?($2)}'`
        ??????RSS=`expr?$RSS?+?$TEP`
        ??fi
        done
        RSS=`expr?$RSS?\*?4`
        PageTable=`grep?PageTables?/proc/meminfo?|?awk?'{print?$2}'`
        SlabInfo=`cat?/proc/slabinfo?|awk?'BEGIN{sum=0;}{sum=sum+$3*$4;}END{print?sum/1024/1024}'`

        echo?$RSS"KB",?$PageTable"KB",?$SlabInfo"MB"
        printf?"rss+pagetable+slabinfo=%sMB\n"?`echo?$RSS/1024?+?$PageTable/1024?+?$SlabInfo|bc`
        free?-m

        $?./cm.sh
        7003756KB,?59272KB,?904.334MB
        rss+pagetable+slabinfo=7800.334MB
        ?????????????total???????used???????free?????shared????buffers?????cached
        Mem:?????????48262???????8050??????40211??????????0?????????17????????404
        -/+?buffers/cache:???????7629??????40633
        Swap:?????????2047????????336???????1711

        free報告說7629, 我們的cm腳本報告說7800.3M, 我們的CM多報了171M。
        damn,這又怎么回事呢?


        我們重新校對下我們的計算。我們和nmon來比對下,slab和pagetable的值是吻合的。那最大的問題可能在進程的消耗計算上。
        resident ? resident set size 包括我們使用的各種庫和so等共享的模塊,在前面的計算中我們重復計算了。


        $?pmap?`pgrep?bash`
        ...
        22923:???-bash
        0000000000400000????848K?r-x--??/bin/bash
        00000000006d3000?????40K?rw---??/bin/bash
        00000000006dd000?????20K?rw---????[?anon?]
        00000000008dc000?????36K?rw---??/bin/bash
        00000000013c8000????592K?rw---????[?anon?]
        000000335c400000????116K?r-x--??/lib64/libtinfo.so.5.7
        ...
        0000003ec5220000??????4K?rw---??/lib64/ld-2.12.so
        0000003ec5221000??????4K?rw---????[?anon?]
        0000003ec5800000???1628K?r-x--??/lib64/libc-2.12.so
        ...
        0000003ec5b9c000?????20K?rw---????[?anon?]
        00007f331b910000??96836K?r----??/usr/lib/locale/locale-archive
        00007f33217a1000?????48K?r-x--??/lib64/libnss_files-2.12.so
        ...
        00007f33219af000?????12K?rw---????[?anon?]
        00007f33219bf000??????8K?rw---????[?anon?]
        00007f33219c1000?????28K?r--s-??/usr/lib64/gconv/gconv-modules.cache
        00007f33219c8000??????4K?rw---????[?anon?]
        00007fff5e553000?????84K?rw---????[?stack?]
        00007fff5e5e4000??????4K?r-x--????[?anon?]
        ffffffffff600000??????4K?r-x--????[?anon?]
        ?total???????????108720K


        多出的171M正是共享庫重復計算的部分。
        但是由于每個進程共享的東西都不一樣,我們也沒法知道每個進程是如何共享的,沒法做到準確的區(qū)分。
        所以只能留點小遺憾,歡迎大家來探討。
        總結:內存方面的概念很多,需要深入挖掘!
        祝玩的開心!

        良許個人微信


        添加良許個人微信即送3套程序員必讀資料


        → 精選技術資料共享

        → 高手如云交流社群





        本公眾號全部博文已整理成一個目錄,請在公眾號里回復「m」獲取!

        推薦閱讀:

        一文講透 “進程、線程、協(xié)程”

        Linux screen命令詳解

        Linux進程之如何查看進程詳情?

        5T技術資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機,樹莓派,等等。在公眾號內回復「1024」,即可免費獲?。?!


        瀏覽 38
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            中文字幕在线视频网站国产免费 | 天天艹综合 | 91视频91色 | 天天操天天舔天天爽 | 天天撸天天干天天日 | 啊┅┅快┅┅用力啊黄蓉 | 日韩人妻一区二区 | 丁香婷婷色五月激情综合 | 特级婬片AAAAAAA级 | 韩国三级中文字幕HD久久精品 |