转载:https://blog.csdn.net/lijzheng/article/details/23618365

Proc/pid/maps显示进程映射了的内存区域和访问权限。对应内核中的操作集为proc_pid_maps_op,具体的导出函数为show_map。内核中进程的一段地址空间用一个vm_area_struct结构体表示,所有地址空间存储在task->mm->mmap链表中。

一个文件可以映射到进程的一段内存区域中,映射的文件描述符保存在vm_area_struct->vm_file域中,这种内存区域叫做有名内存区域,相反,属于匿名映射内存区域。Vm_area_struct每项对应解析如下表所示:

内核每进程的vm_area_struct项

/proc/pid/maps中的项

含义

vm_start

“-”前一列,如00377000

此段虚拟地址空间起始地址

vm_end

“-”后一列,如00390000

此段虚拟地址空间结束地址

vm_flags

第三列,如r-xp

此段虚拟地址空间的属性。每种属性用一个字段表示,r表示可读,w表示可写,x表示可执行,p和s共用一个字段,互斥关系,p表示私有段,s表示共享段,如果没有相应权限,则用’-’代替

vm_pgoff

第四列,如00000000

对有名映射,表示此段虚拟内存起始地址在文件中以页为单位的偏移。对匿名映射,它等于0或者vm_start/PAGE_SIZE

vm_file->f_dentry->d_inode->i_sb->s_dev

第五列,如fd:00

映射文件所属设备号。对匿名映射来说,因为没有文件在磁盘上,所以没有设备号,始终为00:00。对有名映射来说,是映射的文件所在设备的设备号

vm_file->f_dentry->d_inode->i_ino

第六列,如9176473

映射文件所属节点号。对匿名映射来说,因为没有文件在磁盘上,所以没有节点号,始终为00:00。对有名映射来说,是映射的文件的节点号

第七列,如/lib/ld-2.5.so

对有名来说,是映射的文件名。对匿名映射来说,是此段虚拟内存在进程中的角色。[stack]表示在进程中作为栈使用,[heap]表示堆。其余情况则无显示

下面一起看下一个proc maps的例子。

cat /proc/19970/task/19970/maps

001f7000-00212000 r-xp 00000000 fd:00 2719760    /lib/ld-2.5.so

00212000-00213000 r-xp 0001a000 fd:00 2719760    /lib/ld-2.5.so

00213000-00214000 rwxp 0001b000 fd:00 2719760    /lib/ld-2.5.so

00214000-0036b000 r-xp 00000000 fd:00 2719767    /lib/libc-2.5.so

0036b000-0036d000 r-xp 00157000 fd:00 2719767    /lib/libc-2.5.so

0036d000-0036e000 rwxp 00159000 fd:00 2719767    /lib/libc-2.5.so

0036e000-00371000 rwxp 0036e000 00:00 0

0054f000-00565000 r-xp 00000000 fd:00 2719791    /lib/libpthread-2.5.so

00565000-00566000 r-xp 00015000 fd:00 2719791    /lib/libpthread-2.5.so

00566000-00567000 rwxp 00016000 fd:00 2719791    /lib/libpthread-2.5.so

00567000-00569000 rwxp 00567000 00:00 0

006f5000-006f6000 r-xp 006f5000 00:00 0          [vdso]

08048000-08049000 r-xp 00000000 fd:00 3145810    /home/lijz/code/pthread

08049000-0804a000 rw-p 00000000 fd:00 3145810    /home/lijz/code/pthread

08c50000-08c71000 rw-p 08c50000 00:00 0          [heap]

b75d7000-b75d8000 ---p b75d7000 00:00 0

b75d8000-b7fda000 rw-p b75d8000 00:00 0

b7fe4000-b7fe5000 rw-p b7fe4000 00:00 0

bf987000-bf99c000 rw-p bffea000 00:00 0          [stack]

进程的每段地址空间由struct vm_area_struct 描述。如上所示的每一行对应一个vm_area_struct结构体。一个文件可以映射到内存中,vm_area_struct的vm_file保存了文件描述符,这种映射称为有名映射,反之则为匿名映射。下面以第十四行为例,解释各例的内容。

第一列:08049000-0804a000-----本段内存映射的虚拟地址空间范围,对应vm_area_struct中的vm_start和vm_end。

第二列:rw-p----权限 r-读,w-写 x-可执行 p-私有,对应vm_flags。

第三列:00000000----针对有名映射,指本段映射地址在文件中的偏移,对应vm_pgoff。对匿名映射而言,为vm_area_struct->vm_start。

第四列:fd:00----所映射的文件所属设备的设备号,对应vm_file->f_dentry->d_inode->i_sb->s_dev。匿名映射为0。其中fd为主设备号,00为次设备号。

第五列:3145810----文件的索引节点号,对应vm_file->f_dentry->d_inode->i_ino,与ls –i显示的内容相符。匿名映射为0。

第六列:/home/lijz/code/pthread---所映射的文件名。对有名映射而言,是映射的文件名,对匿名映射来说,是此段内存在进程中的作用。[stack]表示本段内存作为栈来使用,[heap]作为堆来使用,其他情况则为无。

经过上面的分析,proc maps中的每一列代表的意思已经非常清晰了。接下来看下proc每maps中每一行的解析。各共享库的代码段,存放着二进制可执行的机器指令,由kernel把该库ELF文件的代码段map到虚存空间;各共享库的数据段,存放着程序执行所需的全局变量,由kernel把ELF文件的数据段map到虚存空间;用户代码段,存放着二进制形式的可执行的机器指令,由kernel把ELF文件的代码段map到虚存空间;用户数据段,存放着程序执行所需的全局变量,由kernel把ELF文件的数据段map到虚存空间;堆(heap),当且仅当malloc调用时存在,由kernel把匿名内存map到虚存空间,堆则在程序中没有调用malloc的情况下不存在;栈(stack),作为进程的临时数据区,由kernel把匿名内存map到虚存空间,栈空间的增长方向是从高地址到低地址。

pthread这个应用程序在maps中占用了两行,内容如下:

08048000-08049000 r-xp 00000000 fd:00 3145810    /home/lijz/code/pthread

08049000-0804a000 rw-p 00000000 fd:00 3145810    /home/lijz/code/pthread

其中第一行的权限是只读,并且可执行,说明第一行是应用程序的代码段,而第二行的权限是可读可写,但是没有执行权限,说明该段是pthread的数据段。

00c56000-00dad000 r-xp 00000000 fd:00 2719767    /lib/libc-2.5.so

00dad000-00daf000 r-xp 00157000 fd:00 2719767    /lib/libc-2.5.so

00daf000-00db0000 rwxp 00159000 fd:00 2719767    /lib/libc-2.5.so

以上是libc-2.5共享库在maps文件中的记录,每个共享库在maps文件中对应着三行,分别是数据段与代码段。

堆[heap]段。

08c64000-08c85000 rw-p 08c64000 00:00 0          [heap]

有些maps文件并不会出现该记录,这主要跟程序中有无使用malloc相关,如果主线程使用了malloc就会有该记录,否则就没有。在子线程中调用malloc,会产生另外的堆映射,但是并不会标记[heap]。例如,在子线程中动态分配1MB的内存空间,pthread2应用程序的执行结果如下所示:

tid addr 0xbfd818f0

child thread run

stackbase 0xb7f4f3c0

stackaddr =0x7754e008----malloc分配的地址

guardsize 4096

对应的maps文件:

08048000-08049000 r-xp 00000000 fd:00 3145811    /home/lijz/code/pthread2

08049000-0804a000 rw-p 00000000 fd:00 3145811    /home/lijz/code/pthread2

0945a000-0947b000 rw-p 0945a000 00:00 0          [heap]

7754e000-b754f000 rw-p 7754e000 00:00 0 -----------区间大小正是1MB

b754f000-b7550000 ---p b754f000 00:00 0

b7550000-b7f52000 rw-p b7550000 00:00 0

b7f5c000-b7f5d000 rw-p b7f5c000 00:00 0

bfd6e000-bfd83000 rw-p bffea000 00:00 0          [stack]

maps文件中红色标注的行,从内容上看,本段内存大小是1MB,权限为读写私有,偏移为本段内存的开始地址,设备号和文件索引节点为0。可以看出本段内存是进程通过mmap映射的一段空间,是匿名映射。在pthread2程序中,正好用malloc分配了一个1MB的内存,能够与这段内存对应。同时,malloc分配的地址0x7754e008正落在该区间,并且偏向区间低地址部分,说明该区间是个堆地址空间。说明了这段1M的内存确实是进程调用malloc分配的,其中malloc又调用mmap系统调用匿名映射。

栈段[stack],下面用几个例子来说明栈段。

bfd50000-bfd65000 rw-p bffea000 00:00 0          [stack]

对于单线程应用程序而言,只有一个[stack]段,对应多线程应用程序,[stack]段是主线程的栈空间,子线程的栈空间则用pthread库自动分配。

例1,将一个单线程的应用的局部变量的地址打印出来,执行的结果如下所示:

./pthread2

tid addr 0xbfc73600

对应的maps文件:

08048000-08049000 r-xp 00000000 fd:00 3145811    /home/lijz/code/pthread2

08049000-0804a000 rw-p 00000000 fd:00 3145811    /home/lijz/code/pthread2

b7f7e000-b7f80000 rw-p b7f7e000 00:00 0

b7f8a000-b7f8b000 rw-p b7f8a000 00:00 0

bfc5f000-bfc74000 rw-p bffea000 00:00 0          [stack]

局部变量的地址0xbfc73600在[stack]区间。

例2:将一个拥有一个子线程的应用局部变量打印出来,执行的结果如下所示:

tid addr 0xbfd64740---------主线程中打印的局部变量地址

child thread run

stackaddr   0xb7fc93c4--------子线程中打印的局部变量地址

guardsize 4096---------栈保护页大小

对应的maps文件如下:

08048000-08049000 r-xp 00000000 fd:00 3145811    /home/lijz/code/pthread2

08049000-0804a000 rw-p 00000000 fd:00 3145811    /home/lijz/code/pthread2

08c64000-08c85000 rw-p 08c64000 00:00 0          [heap]

b75c9000-b75ca000 ---p b75c9000 00:00 0---------pthread_create默认的栈溢出保护区

b75ca000-b7fcc000 rw-p b75ca000 00:000------------pthread_create创建的子线程的栈空间

b7fd6000-b7fd7000 rw-p b7fd6000 00:00 0------------------4KB应该也是通过mmap产生的匿名映射

bfd50000-bfd65000 rw-p bffea000 00:00 0          [stack]---------主进程的栈空间

由上执行结果显示,主线程中局部变量地址0xbfd64740落在[stack]区间,而子线程局部变量地址0xb7fc93c4则落在b75ca000-b7fcc000 rw-p b75ca00区间,并且局部变量的地址从高地址开始分配,说明该VMA正是子线程的栈地址空间。另外,对栈空间,pthread默认设置了一个4KB的栈保护页,对应的区间为:b75c9000-b75ca000---p b75c9000,该区间不可读,不可写,也不能执行,通过这些属性信息的设置,可以达到栈溢出保护的作用。

例3:在例2的基础上,多创建一个线程,pthread2程序的执行结果如下所示:

./pthread2

tid addr 0xbfc81610----------主线程局部变量地址

child thread run

stackaddr = 0xb7f183c0-------子线程1局部变量地址

guardsize 4096

child thread2 run

stackaddr =0xb75173c4 ----------子线程局部变量地址

guardsize 4096

对应的maps文件:

08048000-08049000 r-xp 00000000 fd:00 3145811    /home/lijz/code/pthread2

08049000-0804a000 rw-p 00000000 fd:00 3145811    /home/lijz/code/pthread2

092d6000-092f7000 rw-p 092d6000 00:00 0          [heap]

76b16000-b6b17000 rw-p 76b16000 00:00 0 ----------mallocmmap

b6b17000-b6b18000 ---p b6b17000 00:00 0

b6b18000-b7518000 rw-p b6b18000 00:000---------pthread thread2 stack space

b7518000-b7519000 ---p b7518000 00:00 0

b7519000-b7f1b000 rw-p b7519000 00:000----------pthread thread1 stack space

b7f25000-b7f26000 rw-p b7f25000 00:00 0

bfc6e000-bfc83000 rw-p bffea000 00:00 0          [stack]---main thread stack space

从maps文件记录上看,增加一个子线程,在maps文件中就增加了两条记录,分别是子线程的栈空间和栈保护页的记录。默认情况下,pthread为子线程预留的栈空间大小为1MB,栈保护页为4KB(这主要跟页大小相关)。

总之,proc maps文件可以查看进程的内存映射,每一段内存的权限属性等信息。
---------------------
作者:cjpx84
来源:CSDN
原文:https://blog.csdn.net/lijzheng/article/details/23618365
版权声明:本文为博主原创文章,转载请附上博文链接!

linux proc/xx/maps文件分析相关推荐

  1. linux /proc/net/tcp 文件分析

    /proc/net/tcp文件提供了tcp的连接信息,是由net/ipv4/tcp_ipv4.c中的tcp4_seq_show()实现信息打印的 本文内容来源于 linux官方文档proc_net_t ...

  2. linux物理内存地址与iomem,一种Linux系统物理内存镜像文件分析方法_4

    模块信息,如图7所示,给出了本发明的实施例中 模块结构关系图,modules变量指向某一个已加载模块结构体module地址,所有已加载模 块其module形成一个双向链表,如图7所示,据此可以获取到所 ...

  3. proc/[pid]/maps 文件解释

    proc/[pid]/maps 文件解释 查看进程的虚拟地址空间是如何使用的.  该文件有6列,分别为:  地址:库在进程里地址范围 权限:虚拟内存的权限,r=读,w=写,x=,s=共享,p=私有: ...

  4. 进程内存分配和/proc/xxx/maps简单分析

    参考:http://blog.163.com/tao198352__4232/blog/static/8502064520105611157897/ :http://blog.chinaunix.ne ...

  5. /proc/xx/maps命令

    最近学习一下linux内核相关的,利用/proc/pid/maps可以查看进程的虚拟空间布局,从而获知当前使用内存的具体分布情况. [root@localhost ~]# cat /proc/728/ ...

  6. Linux /proc与/sys目录分析

    proc与sys目录分析 基于Apollo,gingerbread,公版(LeOs之后还会加一些接口的,不予分析) 具体标准接口,可见linux代码documents/proc.txt在这里不做赘述, ...

  7. linux帐户管理命令和文件分析

     linux帐户管理命令 1.创建用户 新的用户可以使用useradd命令创建 2.创建组 增加一个新用户组可以使用 groupadd命令. 格式: groupadd  选项  用户组 常用的选项: ...

  8. Linux系统 proc self,linux – / proc / self / maps中的“— p”权限是什么意思?

    我理解rwxps位的含义. r-xp用于.text. rw -p用于.data / .bss / heap / stack.只是- p页有什么用? 例如,请参阅cat / proc / self / ...

  9. linux内核head.S文件分析

    1:内核运行的物理地址与虚拟地址 (1)KERNEL_RAM_VADDR(VADDR就是virtual address),这个宏定义了内核运行时的虚拟地址.值为0xC0008000 (2)KERNEL ...

最新文章

  1. 中key的用途_Micro Focus Operations Bridge Manager中的多个(RCE)漏洞
  2. XXL-CONF v1.4.1 发布,分布式配置管理平台
  3. chrome 插件安装:无法添加来自此网站的应用,解决办法。安装本地crx插件方法
  4. Pxe+Kickstart批量网络安装操作系统
  5. TCP、UDP相关协议使用的端口号
  6. Caffe中如果高效实现卷积层
  7. C#开发终端式短信的原理和方法 .
  8. 完成端口可用回射服务器
  9. 判断double_深入解析单例模式之懒汉模式---Double-Check及volatile关键字
  10. 11.正则返回不是组的内容
  11. Visio2016 安装教程
  12. 数学建模计算机模拟实验答案,数学建模与数学实验课后习题答案.doc
  13. 关于spring security的URL路径验证问题
  14. PHP、TP5生成下载word
  15. 【科学文献计量】知识单元的频次统计与分布(简单阅览和完整频次统计)
  16. CVE-2019-11478 Sack SlownessExcess Resource Usage漏洞解析与利用
  17. bios找不到硬盘模式选项如何解决?
  18. 安卓手机突然很卡_安卓手机为什么很卡 安卓手机卡顿原因分析【详解】
  19. 使用代理后,雷鸟连接qq邮箱
  20. 学报格式和论文格式一样吗_学报论文发表格式有什么要求

热门文章

  1. 隐藏探针显示php版本号,修改版雅黑PHP探针 支持PHP7+(v0.4.7.2)
  2. 市政管网检测机器人收费标准_管道无损CCTV检测:复杂的地下管网工作,其实可以交给机器人来做...
  3. 嵌入式linux 升级,嵌入式Linux的OTA更新,基本原理和实现
  4. matlab在测量数据处理中的应用,MATLAB在测量数据处理中的应用
  5. java 定时器获得外部参数_JMeter定时器使用小结
  6. 查看本地oracle密码,Oracle 本地验证和密码文件
  7. epoll监听文件_怎么理解把标准输入以ET模式加入epoll,监听EPOLLOUT事件时,epoll_wait多次返回?...
  8. (一)神经网络训练不起来怎么办:局部最小值(local minia)与鞍点(saddle point)
  9. RANSAC算法(2):(拟合平面)本文以地面为基础以及源码分布解读
  10. PT100热电阻校准模块设计