日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

一 前言

內存對于系統(tǒng)資源來說,非常重要,內存問題可以導致系統(tǒng)延遲增大,系統(tǒng)內存泄漏,進程被kill等多種嚴重問題,所以分析進程的內存占用很有必要。本文重點分析了程序中動態(tài)申請內存的情況。

注意所有測試是 5.13.0-52內核條件下測試的,不同的內核測試環(huán)境,內存分類會有很大的不同。

二 程序內存結構

在linux 32位系統(tǒng)中默認虛擬的內存布局如下:

linux中申請內存的情況分析

 

說明:

在linux中每個進程都有各自的虛擬內存空間,空間的大小和cpu的位數(shù)決定了虛擬空間的上限,比如在32位系統(tǒng)下,硬件可以訪問的內存空間上限是4GB,這4GB的空間也不是完全可以給應用程序使用。

整個內存空間分為兩個部分,操作系統(tǒng)占用一部分,從地址0xC0000000到0xFFFFFFFF這1GB的空間。剩下的從0x00000000到0xBFFFFFFF共3GB空間共3GB空間;

ELF可執(zhí)行文件將整個虛擬內存空間分為多個segment;

操作系統(tǒng)是通過VMA 對進程的虛擬內存空間進行管理的。

VMA 是virtual Memory Area的簡稱,一個簡單的程序VMA展示如下:

root@ubuntu-lab:/sys/kernel/debug/tracing# cat /proc/9776/maps
5655a000-5655b000 r--p 00000000 fd:00 1193979                            /home/miao/c-test/mm-test/a.out
5655b000-5655c000 r-xp 00001000 fd:00 1193979                            /home/miao/c-test/mm-test/a.out
5655c000-5655d000 r--p 00002000 fd:00 1193979                            /home/miao/c-test/mm-test/a.out
5655d000-5655e000 r--p 00002000 fd:00 1193979                            /home/miao/c-test/mm-test/a.out
5655e000-5655f000 rw-p 00003000 fd:00 1193979                            /home/miao/c-test/mm-test/a.out
5746c000-5748e000 rw-p 00000000 00:00 0                                  [heap]
f7d83000-f7da3000 r--p 00000000 fd:00 546008                             /usr/lib32/libc.so.6
f7da3000-f7f1f000 r-xp 00020000 fd:00 546008                             /usr/lib32/libc.so.6
f7f1f000-f7fa4000 r--p 0019c000 fd:00 546008                             /usr/lib32/libc.so.6
f7fa4000-f7fa5000 ---p 00221000 fd:00 546008                             /usr/lib32/libc.so.6
f7fa5000-f7fa7000 r--p 00221000 fd:00 546008                             /usr/lib32/libc.so.6
f7fa7000-f7fa8000 rw-p 00223000 fd:00 546008                             /usr/lib32/libc.so.6
f7fa8000-f7fb2000 rw-p 00000000 00:00 0 
f7fbc000-f7fbe000 rw-p 00000000 00:00 0 
f7fbe000-f7fc2000 r--p 00000000 00:00 0                                  [vvar]
f7fc2000-f7fc4000 r-xp 00000000 00:00 0                                  [vdso]
f7fc4000-f7fc5000 r--p 00000000 fd:00 546004                             /usr/lib32/ld-linux.so.2
f7fc5000-f7fe8000 r-xp 00001000 fd:00 546004                             /usr/lib32/ld-linux.so.2
f7fe8000-f7ff5000 r--p 00024000 fd:00 546004                             /usr/lib32/ld-linux.so.2
f7ff6000-f7ff8000 r--p 00031000 fd:00 546004                             /usr/lib32/ld-linux.so.2
f7ff8000-f7ff9000 rw-p 00033000 fd:00 546004                             /usr/lib32/ld-linux.so.2
ffe18000-ffe39000 rw-p 00000000 00:00 0                                  [stack]

說明:

  1. 第一列VMA的地址范圍;(虛擬地址)
  2. 第二列VMA的權限,r標識可讀,w標識可寫,x標識可執(zhí)行,p 標識私有,s標識共享;
  3. 第三列偏移,表示VMA對應的Segment在映像文件中的便宜;
  4. 第四列一般表示映像文件所在設備的主設備號:次設備號,這里面主設備號大多顯示為fd,難道是一個原因?非文件映射的內存,比如堆和棧,則這兩位顯示為00:00
  5. 第五列 標識映射文件的節(jié)點號;
  6. 第六列標識映射的具體文件,可以看到除了程序文件外,還有使用的庫的文件信息。 vdso 為特殊的VMA,用于和內核進行交互。

采用的代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


int g_int = 123;

static g_static_int2 = 456;
static g_static_int_not_init;


int main(void)
{
  int l_int = 3;
  int l_int2 = 4;

  static l_static_int =6;
  static l_static_int2;


  int * pint = (int*)malloc(sizeof(int));
  *pint = 12;

  printf("g_int:%d,tg_static_int2:%d tg_static_int_not_init:%d n",g_int,g_static_int2,g_static_int_not_init);
  printf("g_int:%p,tg_static_int2:%p tg_static_int_not_init:%p n",&g_int,&g_static_int2,&g_static_int_not_init);
  
  printf("l_int:%d tl_int2:%d tl_static_int:%d,tl_static_int2:%d,tpint:%dn",l_int,l_int2,l_static_int,l_static_int2,*pint);
  printf("l_int:%p tl_int2:%p tl_static_int:%p,tl_static_int2:%p,tpint:%pn",&l_int,&l_int2,&l_static_int,&l_static_int2,pint);
  while(1) {
    sleep(3);
    printf("PID:%dn",getpid());
  }
  free(pint);
  return 0;
}

多次運行可以發(fā)現(xiàn)我們變量的地址在其應該對應的空間內,同時發(fā)現(xiàn)每次堆和stack的地址是每次不同的,這也是為了安全期間,設置的隨機偏移。

順便說下stack為主線程的棧,最大的大小默認是ulimit -s ,一般為8MB,pthread_create 創(chuàng)建的棧大小一般為2MB,不同架構不同而且和ulimit 設置的大小有關,也可以自行更改。

三 計算程序內存大小

至于程序內存使用大小,比較簡單的方法是top -p pid 直接看到如下:

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                            
  12375 miao      20   0    2764    852    788 S   0.0   0.0   0:00.00 a.out                                              

VIRT即虛擬內存大小,RES即實際內存大小,這兩個一般最重要,就夠了。 如果按照每個VMA計算,求和,可以通過/proc/pid/smaps文件去計算,這個文件比maps的文件更詳細,值得仔細分析,計算驗證下:

cat /proc/12375/smaps|grep Size|grep -v Page|awk -F: '{print $2}'|awk '{sum += $1}; END {print sum}'
2764

虛擬內存對的上,實際內存計算:

# cat /proc/12375/smaps|grep Rss|grep -v Page|awk -F: '{print $2}'|awk '{sum += $1}; END {print sum}'
1388

這個和實際內存對不上,按照Pss(即共享內存做了平分處理后,仍然有差距),差距原因是應用申請內存通過c的庫申請的,庫申請的時候也會多申請一些,還有一些對齊之類的,有些差異可能也正常。

還有個比較簡單的計算程序內存的方法:

oot@ubuntu-lab:/home/miao/c-test/mm-test# cat /proc/24546/status
Name:   a.out
Umask:  0002
State:  S (sleeping)
Tgid:   24546
Ngid:   0
Pid:    24546
PPid:   5359
TracerPid:      0
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000
FDSize: 256
Groups: 4 24 27 30 46 110 1000 
NStgid: 24546
NSpid:  24546
NSpgid: 24546
NSsid:  5359
VmPeak:  1051332 kB
VmSize:  1051332 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:   1049776 kB
VmRSS:   1049776 kB
RssAnon:         1048672 kB
RssFile:            1104 kB
RssShmem:              0 kB
....

VmRSS 這個即是程序占用的內存,一般情況下VmRSS = RssAnon+RssFile+RssShmem

四 系統(tǒng)內存分析

其實我們遇到系統(tǒng)的性能問題,如果懷疑是內存問題,那么很有可能用free命令看下,然后top命令看看,top下對程序的占用內存情況進行排序,找到可疑進程,然后再做上面的進程占用內存情況的分析。(整個系統(tǒng)所占內存包括內核占的內存和應用程序所占內存兩個部分)。

其實最該看的兩個內核導出文件:/proc/meminfo和 /proc/vmstat 前者是內存的占用分類情況,而后者是內存分配,規(guī)整、臟頁回寫等更細節(jié)的內存數(shù)據(jù)的動態(tài)變化,通過這些變化發(fā)現(xiàn)問題,由于后者不是重點,重點來看下前者,在我機器上統(tǒng)計如下:

miao@ubuntu-lab:~$ cat /proc/meminfo 
MemTotal:        4926744 kB    //所有可用的內存大小,物理內存減去預留位和內核使用。系統(tǒng)從加電開始到引導完成,firmware/BIOS要預留一些內存,內核本身要占用一些內存,最后剩下可供內核支配的內存就是MemTotal。這個值在系統(tǒng)運行期間一般是固定不變的,重啟會改變。
MemFree:         3663620 kB  //表示系統(tǒng)尚未使用的內存。
MemAvailable:    4209668 kB //真正的系統(tǒng)可用內存,系統(tǒng)中有些內存雖然已被使用但是可以回收的,比如cache/buffer、slab都有一部分可以回收,所以這部分可回收的內存加上MemFree才是系統(tǒng)可用的內存
Buffers:           78416 kB   //用來給塊設備做緩存的內存,(文件系統(tǒng)的 metadata、pages)
Cached:           661976 kB     //分配給文件緩沖區(qū)的內存,例如vi一個文件,就會將未保存的內容寫到該緩沖區(qū)
SwapCached:            0 kB   //被swap到磁盤上的匿名內存,又一次被拉入內存統(tǒng)計
Active:           325864 kB    //經常使用的高速緩沖存儲器頁面文件大小
Inactive:         618264 kB   //不經常使用的高速緩沖存儲器文件大小
Active(anon):       4564 kB   //活躍的匿名內存
Inactive(anon):   215464 kB   //不活躍的匿名內存
Active(file):     321300 kB    //活躍的文件使用內存
Inactive(file):   402800 kB  //不活躍的文件使用內存
Unevictable:       19372 kB    //不能被釋放的內存頁
Mlocked:           19372 kB   //系統(tǒng)調用 mlock 家族允許程序在物理內存上鎖住它的部分或全部地址空間。這將阻止Linux 將這個內存頁調度到交換空間(swap space),即使該程序已有一段時間沒有訪問這段空間
SwapTotal:       4194300 kB //交換空間總內存
SwapFree:        4194300 kB    //交換空間空閑內存
Dirty:               148 kB              //等待被寫回到磁盤的臟內存
Writeback:             0 kB            //正在被寫回的臟內存
AnonPages:        223144 kB    //未映射頁的內存/映射到用戶空間的非文件頁表大小
MApped:           210380 kB      //映射文件內存
Shmem:             13168 kB      //已經被分配的共享內存,所有tmpfs類型的文件系統(tǒng)占用的空間都計入共享內存
KReclaimable:      60332 kB 
Slab:             137076 kB         //內核數(shù)據(jù)結構緩存
SReclaimable:      60332 kB   //可收回slab內存
SUnreclaim:        76744 kB    //不可收回slab內存
KernelStack:        7568 kB    // 每一個用戶線程都會分配一個kernel stack(內核棧),內核棧雖然屬于線程,但用戶態(tài)的代碼不能訪問,只有通過系統(tǒng)調用(syscall)、自陷(trap)或異常(exception)進入內核態(tài)的時候才會用到,也就是說內核棧是給kernel code使用的。在x86系統(tǒng)上Linux的內核棧大小是固定的8K或16K
PageTables:         5876 kB    //管理內存分頁的索引表(物理內存和虛擬內存映射表)的大小 
NFS_Unstable:          0 kB // The amount, in kibibytes, of NFS pages sent to the server but not yet committed to the stable storage.
Bounce:                0 kB // 有些老設備只能訪問低端內存,比如16M以下的內存,當應用程序發(fā)出一個I/O 請求,DMA的目的地址卻是高端內存時(比如在16M以上),內核將在低端內存中分配一個臨時buffer作為跳轉,把位于高端內存的緩存數(shù)據(jù)復制到此處。這種額外的數(shù)據(jù)拷貝被稱為“bounce buffering”,會降低I/O 性能。大量分配的bounce buffers 也會占用額外的內存。
WritebackTmp:          0 kB    // USE用于臨時寫回緩沖區(qū)的內存
CommitLimit:     6657672 kB       // 系統(tǒng)實際可分配內存總量
Committed_AS:    1742228 kB   // 當前已分配的內存總量
VmallocTotal:   34359738367 kB // 虛擬內存空間能分配的總內存大小
VmallocUsed:       57524 kB       // 虛擬內存空間使用的內存大小
VmallocChunk:          0 kB          // 虛擬內存空間可分配的最大的邏輯連續(xù)的內存大小
Percpu:            89600 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB //AnonHugePages統(tǒng)計的是Transparent HugePages (THP),THP與Hugepages不是一回事,與進程的RSS/PSS是有重疊的,如果用戶進程用到了THP,進程的RSS/PSS也會相應增加
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
FileHugePages:         0 kB
FilePmdMapped:         0 kB
HugePages_Total:       0   //超級大頁總大小如果進程使用了Hugepages,它的RSS/PSS不會增加。
HugePages_Free:        0  //超級大頁空閑大小
HugePages_Rsvd:        0 // 超級大頁剩余內存
HugePages_Surp:        0 // 剩余超級大頁數(shù)量
Hugepagesize:       2048 kB  //超級大頁 尺寸為2MB
Hugetlb:               0 kB
DirectMap4k:      198464 kB //DirectMap所統(tǒng)計的不是關于內存的使用,而是一個反映TLB效率的指標 表示映射為4kB的內存數(shù)量 TLB(Translation Lookaside Buffer)是位于CPU上的緩存,用于將內存的虛擬地址翻譯成物理地址,由于TLB的大小有限,不能緩存的地址就需要訪問內存里的page table來進行翻譯,速度慢很多。
DirectMap2M:     3913728 kB // 表示映射為2MB的內存數(shù)量
DirectMap1G:     1048576 kB // 表示映射為1GB的內存數(shù)量

五 申請內存分析

剛才的系統(tǒng)內存分析,可以分析各類內存的大小,還需要根據(jù)不同種類的內存大小,對應到應用程序里面,是應用程序中申請哪類內存引起的那,所以這個章節(jié)是通過測試程序申請內存看meminfo中各項內存分類的大小變化,從而等到遇到問題的時候就可以通過meminfo中的數(shù)據(jù)猜測到底是哪里數(shù)據(jù)影響的。

下圖左邊是程序通過glibc的庫申請內存,注意這里面的程序也可能是c程序,也可能是JAVA程序,很多語言最終底層申請內存還是通過c的庫來申請,c的庫申請內存的內存主要就有兩種形式,一種是mmap映射的方式,對應虛擬內存的映射內存區(qū),另一種方式是通過brk或sbrk來申請小內存(一般是小于128kb的內存),這些虛擬內存并沒有真實分配,只有真正使用的時候通過缺頁中斷,分配真實的物理內存。

linux中申請內存的情況分析

 

圖來自極客時間

按照內存類型對程序運行所需的內存進行分類,構成如下的思維導圖:

linux中申請內存的情況分析

 

重點需要關注的:

  1. 私有匿名內存,比如我們通過malloc或calloc、或new申請的內存。
  2. 共享匿名內存,tmpfs這里面如果你程序寫臨時文件寫這里面,需要自己負責刪除。
  3. 私有文件映射,比如通過mmap映射讀文件。
  4. 共享文件映射,如果自己申請需要自己釋放。

5.1 malloc申請內存-匿名內存測試

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define SIZE 1024*1024*1024

int main (void)
{
  char * p = (char *) malloc(SIZE);
  memset(p,0x0,SIZE);
  while(1) {
       printf("PID:%dn",getpid());
       sleep(50);
  }
free(p);
return 0;
}

先清理下內存,然后運行此程序,查看/proc/meminfo的變化。

root@ubuntu-lab:/home/miao/c-test/mm-test# diff meminfo.old meminfo.new
2,5c2,5
< MemFree:         4217504 kB
< MemAvailable:    4230356 kB
< Buffers:            2040 kB
< Cached:           218572 kB
---
> MemFree:         3165428 kB
> MemAvailable:    3180980 kB
> Buffers:            4396 kB
> Cached:           218776 kB
7,8c7,8
< Active:            37908 kB
< Inactive:         380112 kB
---
> Active:            40424 kB
> Inactive:        1428872 kB
10,12c10,12
< Inactive(anon):   211228 kB
< Active(file):      35272 kB
< Inactive(file):   168884 kB
---
> Inactive(anon):  1259804 kB
> Active(file):      37788 kB
> Inactive(file):   169068 kB
17c17
< Dirty:               204 kB
---
> Dirty:                12 kB
19,20c19,20
< AnonPages:        217032 kB
< Mapped:           213968 kB
---
> AnonPages:       1265628 kB
> Mapped:           213988 kB
22,27c22,27
< KReclaimable:      33828 kB
< Slab:             109880 kB
< SReclaimable:      33828 kB
< SUnreclaim:        76052 kB
< KernelStack:        7472 kB
< PageTables:         5576 kB
---
> KReclaimable:      33832 kB
> Slab:             109808 kB
> SReclaimable:      33832 kB
> SUnreclaim:        75976 kB
> KernelStack:        7456 kB
> PageTables:         7628 kB
32c32
< Committed_AS:    1732340 kB
---
> Committed_AS:    2781300 kB

重點幾個:

1. Inactive(anon) 增加1GB的非活躍匿名內存;
2. Committed_AS 分配的內存增加了1GB;
3. Inactive 非活躍匿名內存增加1GB;
4. AnonPages 匿名內存頁增加了1GB;
5. MemAvailable 和MemFree 減少了1GB。

5.2 mmap申請私有匿名內存

#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#define MEMSIZE 1024*1024*1024
#define MPFILE "./mmapfile"

int main()
{
    void *ptr;
    int fd;
    fd = open(MPFILE, O_RDWR);
    if (fd < 0) {
        perror("open()");
        exit(1);
    }
// 匿名方式申請的時候會忽略最后兩個參數(shù)的
    ptr = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, fd, 0);
    if (ptr == NULL) {
        perror("mmap()");
        exit(1);
    }
    printf("%pn", ptr);
    bzero(ptr, MEMSIZE);
    printf("pid=%dn", getpid());
    sleep(50);
    munmap(ptr, MEMSIZE);
    close(fd);
    exit(1);
}

結果同上。

5.3 mmap申請匿名共有映射

和上面代碼類似,只是一句代碼不同:

  ptr = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, fd, 0);

主要變化內存:

MemFree: 空閑內存減少1GB。
MemAvailable: 可用內存減少1GB。
Cached:   緩存增加1GB。
Inactive: 增加了1GB。
Inactive(anon): 增加1GB。
Mapped: 增加1GB。
Shmem: 共享內存增加了1GB。
Committed_AS: 申請內存增加了1GB。

5.4 mmap申請私有文件映射內存

和上面的代碼類似,只是:

    ptr = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);

主要變化內存:

1. MemFree 空閑內存少了2GB。
2. MemAvailable 內存少了1GB,因為緩存是可以釋放的。
3. Cached 增加了1GB。
4. Inactive 增加了2GB。
5. Inactive(anon) 增加了1GB。
6. Inactive(file) 增加了1GB。
7. AnonPages 增加了1GB
8. Committed_AS 增加了1GB。

私有文件映射,在進程內存種看到的是占用Inactive(file)內存,只所以也會占用Inactive(anon) ,是在于私有文件映射很特殊,它在寫的時候,不會同步到后臺的文件上去,采用寫時復制,寫時候會拷貝一份到物理內存中(匿名內存)。

5.5 mmap申請共享文件映射

代碼和上面類似不同點:

    ptr = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

結果如下:

1. MemFree 少1GB。
2. Cached 增加了1GB。
3. Inactive 增加了1GB。
4. Inactive(file) 增加了1GB。
5. Mapped 增加了1GB。

注意只有共享內存的mmap才會在Mapped內存,共享內存映射算Cache所以這里面增加了,因為第一次讀文件,所以是Inactive(file),所以增加了1GB。

注意這種方式有兩個有用的點:

  1. 映射的內存是共享的,所以可以多個在多個進程間共享。
  2. 對映射的內存寫入或修改后,系統(tǒng)會自動同步到對應的文件中,這個很好用。

總結

  1. 只要是私有的mmap映射,對于系統(tǒng)看來都是匿名頁面。
  2. 只要是共享的mmap映射,對系統(tǒng)占用的內存都是MMaped內存。

5.6 shm共享內存

代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#define MEMSIZE 1024*1024*1024
int
main()
{
    int shmid;
    char *ptr;
    pid_t pid;
    struct shmid_ds buf;
    int ret;
   // 創(chuàng)建1GB大小權限為0600的共享內存
    shmid = shmget(IPC_PRIVATE, MEMSIZE, 0600);
    if (shmid<0) {
        perror("shmget()");
        exit(1);
    }
   // 獲取共享內存信息復制到buf中,包括權限大小等
    ret = shmctl(shmid, IPC_STAT, &buf);
    if (ret < 0) {
        perror("shmctl()");
        exit(1);
    }
    printf("shmid: %dn", shmid);
    printf("shmsize: %dn", buf.shm_segsz);
 
    pid = fork();
    if (pid<0) {
        perror("fork()");
        exit(1);
    }
   // 子進程
    if (pid==0) {
        // 將共享內存映射到本進程的內存空間
        ptr = shmat(shmid, NULL, 0);
        if (ptr==(void*)-1) {
            perror("shmat()");
            exit(1);
        }
        bzero(ptr, MEMSIZE);
         // 拷貝hello到里面去
        strcpy(ptr, "Hello!");
        exit(0);
    } else {
       // 等子進程寫入結束
        wait(NULL);
     // 將共享內存映射到本進程的內存空間
        ptr = shmat(shmid, NULL, 0);
        if (ptr==(void*)-1) {
            perror("shmat()");
            exit(1);
        }
      // 輸出退出
        puts(ptr);
        exit(0);
    }
}

注意:

  1. 代碼沒有調用int shmdt(const void * shmadr); 來清理共享內存和進程的關聯(lián);
  2. 代碼也未調用 shmctl的IPC_RMID刪除共享內存 來刪除內存,所以程序運行結束,還是會占用共享內存的,如下查看:
root@ubuntu-lab:/home/miao/c-test/mm-test# ipcs -m
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x000631ba 0          postgres   600        56         6                       
0x00000000 3          root       600        1073741824 0      

繼續(xù)看下內存的變化:

1. MemFree 和MemAvailable 減少了1GB。
2. Cached 占用增加了1GB,可見shm是屬于cache的。
3. Inactive 增加了1GB。
4. Inactive(anon) 增加了1GB。
5. Shmem 增加了1GB。
6. Committed_AS增加了1GB。

shm被視為基于tmpfs文件系統(tǒng)的內存頁,既然基于文件系統(tǒng),就不算匿名頁,所以不被計入/proc/meminfo中的AnonPages。

清理共享內存:

root@ubuntu-lab:/home/miao/c-test/mm-test# ipcrm -m 3
root@ubuntu-lab:/home/miao/c-test/mm-test# ipcs -m

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x000631ba 0          postgres   600        56         6   

5.7 tmpfs

測試:

mkdir /tmp/tmpfs
mount -t tmpfs -o size=2G none /tmp/tmpfs/

#占用空間
root@ubuntu-lab:/home/miao/c-test/mm-test# dd if=/dev/zero of=/tmp/tmpfs/testfile bs=1G count=1

1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 3.15495 s, 340 MB/s
root@ubuntu-lab:/home/miao/c-test/mm-test# 
root@ubuntu-lab:/home/miao/c-test/mm-test# df -h
none                               2.0G  1.0G  1.0G  50% /tmp/tmpfs

內存變化:

1. MemFree 和MemAvailable 減少了1GB。
2. Cached 占用增加了1GB,可見shm是屬于cache的。
3. Inactive 增加了1GB。
4. Inactive(anon) 增加了1GB。
5. Shmem 增加了1GB。
6. Committed_AS增加了1GB。

和shm一樣的內存變化,注意用:echo 3 > /proc/sys/vm/drop_caches 并不會釋放內存,而且通過free -h 可以看到有1GB的空間。

root@ubuntu-lab:/home/miao/c-test/mm-test# free -h
               total        used        free      shared  buff/cache   available
Mem:           4.7Gi       474Mi       3.0Gi       1.0Gi       1.2Gi       3.0Gi

清理:

rm /tmp/tmpfs/testfile 
umount  /tmp/tmpfs/

參考:

[linux內存占用分析之meminfo - SegmentFault 思否](https://segmentfault.com/a/1190000022518282)
[/proc/meminfo之謎 | Linux Performance](http://linuxperf.com/?p=142)
代碼來自:深入淺出Linux 內核管理和調試
[https://www.jianshu.com/p/eece39beee20](https://www.jianshu.com/p/eece39beee20)

分享到:
標簽:內存
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定