0%

通过 /proc/PID/maps 分析进程内存分布

通过分析 /proc/PID/maps 文件来了解程序运行时进程内存分布

maps

下面是进程 /dvb/out.elf 及相关 maps 文件的一个实例,其中 898 是主进程:

[root@ /proc]# ps -T
PID   USER     TIME   COMMAND
    1 root       0:00 init
    2 root       0:00 [kthreadd]
    3 root       0:00 [ksoftirqd/0]
    4 root       0:00 [events/0]
    5 root       0:00 [khelper]
   57 root       0:00 [kblockd/0]
   70 root       0:00 [khubd]
   96 root       0:00 [pdflush]
   97 root       0:00 [pdflush]
   98 root       0:00 [kswapd0]
   99 root       0:00 [aio/0]
  100 root       0:00 [nfsiod]
  101 root       0:00 [cifsoplockd]
  102 root       0:00 [cifsdnotifyd]
  739 root       0:00 [mtdblockd]
  790 root       0:01 [rpciod/0]
  822 root       0:00 [gx3211_hdmi_thr]
  862 root       0:00 {exe} telnetd
  868 root       7:56 gdbserver 192.168.110.55:1245 /dvb/out.elf
  898 root       0:40 /dvb/out.elf
  915 root       0:00 /dvb/out.elf
  918 root       4:01 {pMonitor} /dvb/out.elf
  919 root       0:00 {PlayerMsgSchedu} /dvb/out.elf
  924 root       0:00 {NetworkMsgSched} /dvb/out.elf
  925 root      10:12 {NetworkConsoleS} /dvb/out.elf
  926 root       0:39 {parse read} /dvb/out.elf
  927 root       0:00 {EpgMsgScheduler} /dvb/out.elf
  928 root       6:09 {EpgConsoleSched} /dvb/out.elf
  929 root       0:00 {SearchMsgSchedu} /dvb/out.elf
  930 root       0:00 {SearchConsoleSc} /dvb/out.elf
  931 root       0:00 {SiMsgScheduler} /dvb/out.elf
  932 root      15:50 {SiConsoleSchedu} /dvb/out.elf
  933 root       0:00 {BookMsgSchedule} /dvb/out.elf
  934 root       0:23 {BookConsoleSche} /dvb/out.elf
  935 root       0:00 {ExtraMsgSchedul} /dvb/out.elf
  936 root       0:01 {ExtraConsoleSch} /dvb/out.elf
  937 root       0:14 {GuiViewMsgSched} /dvb/out.elf
  938 root       4:24 {GuiViewConsoleS} /dvb/out.elf
  941 root       0:00 {FrontendMsgSche} /dvb/out.elf
  942 root     668:52 {FrontendConsole} /dvb/out.elf
  943 root       0:00 {HotPlugConsoleS} /dvb/out.elf
  944 root       0:00 {update msg} /dvb/out.elf
  945 root       0:05 {update console} /dvb/out.elf
  946 root       0:05 {BlindSearchMsgS} /dvb/out.elf
  947 root       0:14 {BlindSearchCons} /dvb/out.elf
  948 root       0:00 {AppDeamonMsgSch} /dvb/out.elf
  972 root       0:00 {app_ecm_proc} /dvb/out.elf
  993 root       2:06 {apps_service} /dvb/out.elf
  996 root       0:02 {VpnConsoleSched} /dvb/out.elf
  997 root       0:00 {VpnMsgScheduler} /dvb/out.elf
  998 root       0:00 {GuiViewConsoleS} /dvb/out.elf
  999 root       0:00 {app_pmt_proc} /dvb/out.elf
 1000 root       0:00 {ttx_demux_threa} /dvb/out.elf
 1001 root       0:00 {ttx_parse_threa} /dvb/out.elf
  913 root       0:00 -/bin/sh
  914 root       0:00 [kpid-ts-out]
  917 root       0:00 [gx3201_jpeg_thr]
  939 root       0:08 [kdvb-fe-0]
  940 root      12:19 [kdvb-fe-0]
12626 root       0:00 {exe} ps -T

# ls /proc/898/task/
1000  915   924   927   930   933   936   941   944   947   993   998
1001  918   925   928   931   934   937   942   945   948   996   999
898   919   926   929   932   935   938   943   946   972   997

# cat /proc/898/maps
00008000-008ee000 r-xp 00000000 00:0b 261675     /dvb/out.elf
008ee000-009ff000 rw-p 008e5000 00:0b 261675     /dvb/out.elf
009ff000-00c7b000 rwxp 009ff000 00:00 0          [heap]
2aaa8000-2aaa9000 r-xp 2aaa8000 00:00 0          [vdso]
2aaaa000-2eaaa000 rw-s 94000000 00:0c 728        /dev/gxav0
2eaaa000-2eaab000 ---p 2eaaa000 00:00 0
2eaab000-2ebaa000 rw-p 2eaab000 00:00 0
2ebaa000-2ebab000 ---p 2ebaa000 00:00 0
2ebab000-2ecaa000 rw-p 2ebab000 00:00 0
2ecaa000-2ecab000 ---p 2ecaa000 00:00 0
2ecab000-2edaa000 rw-p 2ecab000 00:00 0
2edaa000-2edab000 ---p 2edaa000 00:00 0
2edab000-2eeaa000 rw-p 2edab000 00:00 0
2eeaa000-2eeab000 ---p 2eeaa000 00:00 0
2eeab000-2efaa000 rw-p 2eeab000 00:00 0
2efaa000-2efab000 ---p 2efaa000 00:00 0
2efab000-2f0aa000 rw-p 2efab000 00:00 0
2f0aa000-2f0ab000 ---p 2f0aa000 00:00 0
2f0ab000-2f1aa000 rw-p 2f0ab000 00:00 0
2f1aa000-2f1ab000 ---p 2f1aa000 00:00 0
2f1ab000-2f2aa000 rw-p 2f1ab000 00:00 0
2f2aa000-2f2ab000 ---p 2f2aa000 00:00 0
2f2ab000-2f3aa000 rw-p 2f2ab000 00:00 0
2f3aa000-2f3ab000 ---p 2f3aa000 00:00 0
2f3ab000-2f4aa000 rw-p 2f3ab000 00:00 0
2f4aa000-2f4ab000 ---p 2f4aa000 00:00 0
2f4ab000-2f60f000 rw-p 2f4ab000 00:00 0
2f60f000-2f610000 ---p 2f60f000 00:00 0
2f610000-2f70f000 rw-p 2f610000 00:00 0
2f70f000-2f710000 ---p 2f70f000 00:00 0
2f710000-2f80f000 rw-p 2f710000 00:00 0
2f80f000-2f810000 ---p 2f80f000 00:00 0
2f810000-2f90f000 rw-p 2f810000 00:00 0
2f90f000-2f910000 ---p 2f90f000 00:00 0
2f910000-2fa0f000 rw-p 2f910000 00:00 0
2fa0f000-2fa10000 ---p 2fa0f000 00:00 0
2fa10000-2fb0f000 rw-p 2fa10000 00:00 0
2fb0f000-2fb10000 ---p 2fb0f000 00:00 0
2fb10000-2fc0f000 rw-p 2fb10000 00:00 0
2fc0f000-2fc10000 ---p 2fc0f000 00:00 0
2fc10000-2fd0f000 rw-p 2fc10000 00:00 0
2fd0f000-2fd10000 ---p 2fd0f000 00:00 0
2fd10000-2fe0f000 rw-p 2fd10000 00:00 0
2fe0f000-2fe10000 ---p 2fe0f000 00:00 0
2fe10000-2ff0f000 rw-p 2fe10000 00:00 0
2ff0f000-2ff10000 ---p 2ff0f000 00:00 0
2ff10000-3000f000 rw-p 2ff10000 00:00 0
3000f000-30010000 ---p 3000f000 00:00 0
30010000-3010f000 rw-p 30010000 00:00 0
3010f000-30110000 ---p 3010f000 00:00 0
30110000-3020f000 rw-p 30110000 00:00 0
3020f000-30210000 ---p 3020f000 00:00 0
30210000-3030f000 rw-p 30210000 00:00 0
3030f000-30310000 ---p 3030f000 00:00 0
30310000-3040f000 rw-p 30310000 00:00 0
3040f000-30410000 ---p 3040f000 00:00 0
30410000-3050f000 rw-p 30410000 00:00 0
3050f000-30510000 ---p 3050f000 00:00 0
30510000-306ff000 rw-p 30510000 00:00 0
306ff000-30700000 ---p 306ff000 00:00 0
30700000-307ff000 rw-p 30700000 00:00 0
307ff000-30800000 ---p 307ff000 00:00 0
30800000-308ff000 rw-p 30800000 00:00 0
308ff000-30900000 ---p 308ff000 00:00 0
30900000-309ff000 rw-p 30900000 00:00 0
309ff000-30a00000 ---p 309ff000 00:00 0
30a00000-30aff000 rw-p 30a00000 00:00 0
30aff000-30b00000 ---p 30aff000 00:00 0
30b00000-31500000 rw-p 30b00000 00:00 0
31500000-31501000 ---p 31500000 00:00 0
31501000-31600000 rw-p 31501000 00:00 0
31600000-31601000 ---p 31600000 00:00 0
31601000-31700000 rw-p 31601000 00:00 0
31700000-31701000 ---p 31700000 00:00 0
31701000-31800000 rw-p 31701000 00:00 0
7fddc000-7fdf1000 rwxp 7ffe2000 00:00 0          [stack]

第一列的是一个段的起始地址和结束地址,第二列这个段的权限,第三列段的段内相对偏移量,第六列是这个段所存放的内容所对应的文件。

对于第二列的权限, r:表示可读, w:表示可写, x:表示可执行, p:表示受保护(即只对本进程有效,不共享),与之相对的是 s,意是就是共享。

进程空间从低到高依次是: 代码段 (r-xp) , 可读写数据段 (rw-p) , , mmap 区(文件映射,匿名映射以及线程栈) , 进程栈

系统创建线程时执行如下代码:

#define GX_PTHREAD_STACK_MIN 0x100000
local_stack_size = stack_size <= GX_PTHREAD_STACK_MIN ? GX_PTHREAD_STACK_MIN : stack_size;
if (pthread_attr_setstacksize(&custom_attr, (size_t)local_stack_size)) {
    printf("pthread_attr_setstacksize error in GxCore_ThreadCreate, Pthread ID = %u\n", thread_rec->handle);
    goto gxcore_err;
}

pthread 库创建线程时会设置 4kguard 区用于栈溢出检测,因此在 进程 mmap 区 中每两行就是一个 线程栈

31500000-31501000 ---p 31500000 00:00 0     // guard size 0x1000
31501000-31600000 rw-p 31501000 00:00 0     // thread size 0x100000
31600000-31601000 ---p 31600000 00:00 0
31601000-31700000 rw-p 31601000 00:00 0
31700000-31701000 ---p 31700000 00:00 0
31701000-31800000 rw-p 31701000 00:00 0

同时可以计算出进程栈范围为 7fddc000-7fdf1000,大小为 84K

out.elf

分析可执行文件, readelf -a out.elf

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           MCORE
  Version:                           0x1
  Entry point address:               0x80e0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          20109200 (bytes into file)
  Flags:                             0x10002002
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         4
  Size of section headers:           40 (bytes)
  Number of section headers:         30
  Section header string table index: 27

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .init             PROGBITS        000080b4 0000b4 000022 00  AX  0   0  4
  [ 2] .text             PROGBITS        000080e0 0000e0 73407e 00  AX  0   0 16
  [ 3] .fini             PROGBITS        0073c160 734160 000016 00  AX  0   0  4
  [ 4] .rodata           PROGBITS        0073c180 734180 18d168 00   A  0   0 16
  [ 5] .eh_frame         PROGBITS        008c92e8 8c12e8 024634 00   A  0   0  4
  [ 6] .gcc_except_table PROGBITS        008ee91c 8e591c 00c780 00  WA  0   0  4
  [ 7] .tdata            PROGBITS        008fb09c 8f209c 000004 00 WAT  0   0  4
  [ 8] .tbss             NOBITS          008fb0a0 8f20a0 000010 00 WAT  0   0  4
  [ 9] .ctors            PROGBITS        008fb0a0 8f20a0 0001d0 00  WA  0   0  4
  [10] .dtors            PROGBITS        008fb270 8f2270 0000b8 00  WA  0   0  4
  [11] .jcr              PROGBITS        008fb328 8f2328 000004 00  WA  0   0  4
  [12] .data.rel.ro      PROGBITS        008fb330 8f2330 000ab8 00  WA  0   0  8
  [13] .got              PROGBITS        008fbde8 8f2de8 0003c8 04  WA  0   0  4
  [14] .data             PROGBITS        008fc1b0 8f31b0 102b24 00  WA  0   0 16
  [15] .bss              NOBITS          009fecd8 9f5cd4 08fe78 00  WA  0   0  8
  [16] .comment          PROGBITS        00000000 9f5cd4 0000c6 01  MS  0   0  1
  [17] .debug_aranges    PROGBITS        00000000 9f5d9a 008db8 00      0   0  1
  [18] .debug_pubnames   PROGBITS        00000000 9feb52 034b26 00      0   0  1
  [19] .debug_info       PROGBITS        00000000 a33678 413c50 00      0   0  1
  [20] .debug_abbrev     PROGBITS        00000000 e472c8 055324 00      0   0  1
  [21] .debug_line       PROGBITS        00000000 e9c5ec 245862 00      0   0  1
  [22] .debug_frame      PROGBITS        00000000 10e1e50 04f8e8 00      0   0  4
  [23] .debug_str        PROGBITS        00000000 1131738 09eea4 01  MS  0   0  1
  [24] .debug_loc        PROGBITS        00000000 11d05dc 0d25b7 00      0   0  1
  [25] .debug_pubtypes   PROGBITS        00000000 12a2b93 0654e5 00      0   0  1
  [26] .debug_ranges     PROGBITS        00000000 1308078 0255f8 00      0   0  1
  [27] .shstrtab         STRTAB          00000000 132d670 00011d 00      0   0  1
  [28] .symtab           SYMTAB          00000000 132dc40 09bb30 10     29 19497  4
  [29] .strtab           STRTAB          00000000 13c9770 0cdb06 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00008000 0x00008000 0x8e591c 0x8e591c R E 0x1000
  LOAD           0x8e591c 0x008ee91c 0x008ee91c 0x1103b8 0x1a0234 RW  0x1000
  TLS            0x8f209c 0x008fb09c 0x008fb09c 0x00004 0x00014 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4

 Section to Segment mapping:
  Segment Sections...
   00     .init .text .fini .rodata .eh_frame
   01     .gcc_except_table .tdata .ctors .dtors .jcr .data.rel.ro .got .data .bss
   02     .tdata .tbss
   03

可以看到:

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00008000 0x00008000 0x8e591c 0x8e591c R E 0x1000
  LOAD           0x8e591c 0x008ee91c 0x008ee91c 0x1103b8 0x1a0234 RW  0x1000
  TLS            0x8f209c 0x008fb09c 0x008fb09c 0x00004 0x00014 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4

 Section to Segment mapping:
  Segment Sections...
   00     .init .text .fini .rodata .eh_frame
   01     .gcc_except_table .tdata .ctors .dtors .jcr .data.rel.ro .got .data .bss
   02     .tdata .tbss
   03

对应进程第一、第二段内容及大小, 只读数据段 被合并到 text

Ref

  1. 三言两语聊 kernel:线程栈
  2. 程序运行时的内存空间分布
  3. linux proc maps 文件分析
  4. proc 进程信息解析