2026/3/17 13:57:08
网站建设
项目流程
门户网站的特征,wordpress恶意广告,建设银行个人网上银行登录,高校专业建设五大要素概述
/proc/pid/maps 是 Linux 系统提供的重要调试接口#xff0c;用于查看进程的虚拟内存布局。本文档详细介绍如何解读这些信息并用于调试内存相关问题。
1. 基本格式
/proc/pid/maps 文件的每一行代表一个虚拟内存区域#xff08;VMA - Virtual Memory…概述/proc/pid/maps是 Linux 系统提供的重要调试接口用于查看进程的虚拟内存布局。本文档详细介绍如何解读这些信息并用于调试内存相关问题。1. 基本格式/proc/pid/maps文件的每一行代表一个虚拟内存区域VMA - Virtual Memory Areaaddress perms offset dev inode pathname 00400000-00452000 r-xp 00000000 08:02 173521 /usr/bin/dbus-daemon 7f7fcfe00000-7f7fcfe01000 ---p 00000000 00:00 0字段含义示例说明address虚拟地址范围7f7fcfe00000-7f7fcfe01000起始地址-结束地址16进制perms访问权限rw-p读/写/执行/共享标志offset文件偏移00000000文件映射的偏移量dev设备号103:02主:次设备号inode文件 inode16804882文件系统 inode 号pathname映射路径/usr/bin/dbus-daemon文件路径或特殊标记匿名映射为空2. 权限标志详解2.1 权限位rwxp │││└─ p private (私有), s shared (共享) ││└── x executable (可执行) │└─── w writable (可写) └──── r readable (可读)2.2 常见权限组合权限含义典型用途r-xp只读可执行程序代码段 (.text)r--p只读只读数据段 (.rodata)、库的只读部分rw-p可读写数据段 (.data/.bss)、堆、栈、匿名内存---p无权限Guard Page保护页访问会触发 SIGSEGVrwxp可读写执行JIT 代码、自修改代码不推荐3. 设备和 inode 说明3.1 设备号00:00- 匿名内存不对应任何文件通过malloc()、mmap(MAP_ANONYMOUS)分配堆、栈103:02等 - 实际设备文件映射共享库、可执行文件、数据文件3.2 Inode0- 匿名映射非零- 文件映射的 inode 号4. 特殊路径标记标记含义[stack]主线程栈[stack:tid]线程栈tid 为线程 ID[heap]进程堆[vdso]虚拟动态共享对象内核快速系统调用[vvar]vDSO 使用的数据页[vsyscall]旧式快速系统调用已废弃[anon:name]命名匿名映射空白普通匿名内存5. 常见内存区域识别5.1 完整示例分析地址范围 权限 偏移 设备 inode 路径# 可执行文件映射00400000-004a0000 r-xp 00000000 08:02123456/usr/bin/app 004a0000-004a1000 r--p 000a0000 08:02123456/usr/bin/app 004a1000-004a2000 rw-p 000a1000 08:02123456/usr/bin/app# 堆004a2000-006b3000 rw-p 00000000 00:000[heap]# 共享库7f1234567000-7f1234590000 r-xp 00000000 08:02789012/lib/libc.so.6 7f1234590000-7f1234790000 ---p 00029000 08:02789012/lib/libc.so.6 ← Guard 7f1234790000-7f1234794000 r--p 00029000 08:02789012/lib/libc.so.6 7f1234794000-7f1234796000 rw-p 0002d000 08:02789012/lib/libc.so.6# 匿名内存mmap 或大分配7f7acfe00000-7f7fcfe00000 rw-p 00000000 00:000← 3GB# 保护页Guard Page7f7fcfe00000-7f7fcfe01000 ---p 00000000 00:000← 危险# 线程栈7ffff7800000-7ffff7821000 rw-p 00000000 00:000[stack]# 内核快速调用7ffff7ffd000-7ffff7fff000 r-xp 00000000 00:000[vdso]5.2 内存布局模式高地址 ↑ │ [stack] 主线程栈 │ [vdso] 内核提供的虚拟 DSO │ 库文件 共享库 (.so) │ 匿名大块 mmap 大分配 │ [heap] 堆 │ .bss/.data 已初始化/未初始化数据 │ .rodata 只读数据 │ .text 代码段 ↓ 低地址6. 调试技巧和工具6.1 快速查询命令PID5220# 查看所有内存区域sudocat/proc/$PID/maps# 查看堆和栈sudocat/proc/$PID/maps|grep-E\[heap\]|\[stack\]# 查看所有匿名内存sudocat/proc/$PID/maps|grep00:00 0# 查看保护页潜在问题区域sudocat/proc/$PID/maps|grep\-\-\-p# 查看可写可执行区域安全风险sudocat/proc/$PID/maps|greprwxp# 统计总内存使用MBsudocat/proc/$PID/maps|awk { split($1, addr, -); start strtonum(0x addr[1]); end strtonum(0x addr[2]); total (end - start); } END { print total / 1024 / 1024 MB }# 按类型统计内存sudocat/proc/$PID/maps|awk { split($1, addr, -); size (strtonum(0x addr[2]) - strtonum(0x addr[1])) / 1024; if ($6 ~ /\.so/) type[Libraries] size; else if ($6 ~ /heap/) type[Heap] size; else if ($6 ~ /stack/) type[Stack] size; else if ($3 00:00) type[Anonymous] size; else type[Other] size; } END { for (t in type) printf %-15s: %10.2f KB\n, t, type[t] }6.2 检查地址有效性#!/bin/bash# check_address.sh - 检查地址是否在有效映射范围内PID$1ADDR$2# 转换地址为十进制ADDR_DEC$((ADDR))sudocat/proc/$PID/maps|whilereadline;do# 提取起始和结束地址range$(echo$line|awk{print $1})start$((0x${range%-*}))end$((0x${range#*-}))perms$(echo$line|awk{print $2})if[$ADDR_DEC-ge$start][$ADDR_DEC-lt$end];thenecho✓ Address$ADDRfound in mapping:echo Range:$rangeecho Permissions:$permsif[$perms---p];thenecho ⚠️ WARNING: This is a guard page (no permissions)!exit1fiexit0fidoneecho✗ Address$ADDRnot found in any mapping!echo This is an unmapped region (accessing it will cause SIGSEGV)exit1使用方法$chmodx check_address.sh $ ./check_address.sh52200x7f7fcfe01000 ✓ Address 0x7f7fcfe01000 foundinmapping: Range: 7f7fcfe00000-7f7fcfe01000 Permissions: ---p ⚠️ WARNING: This is a guard page(no permissions)!7. 常见问题模式7.1 Guard Page 问题症状访问地址时触发 SIGSEGV 或内核返回 -EPERM/-EFAULT识别$sudocat/proc/$PID/maps|grep\-\-\-p.*00:007f7fcfe00000-7f7fcfe01000 ---p 00000000 00:000原因栈溢出保护大内存分配之间的保护区线程栈的保护页解决检查指针运算确保不访问边界外的内存7.2 内存空洞症状地址在两个 VMA 之间没有映射识别# 查找连续地址范围之间的间隙$sudocat/proc/$PID/maps|awk prev_end ! strtonum(0x $1) - prev_end 4096 { gap strtonum(0x $1) - prev_end; printf Gap: %016x - %016x (%d KB)\n, prev_end, strtonum(0x $1), gap/1024 } {split($1, a, -); prev_end strtonum(0x a[2])}解决修正地址计算逻辑7.3 文件映射冲突症状AMDGPU_GEM_USERPTR_ANONONLY 标志冲突识别# 查找文件映射的内存$sudocat/proc/$PID/maps|grep-v00:00 0|grep-v\[v解决使用匿名内存mmap MAP_ANONYMOUS或不设置 ANONONLY 标志8. 总结/proc/pid/maps是调试内存问题的强大工具。关键要点理解权限标志- 特别注意---p(guard page)识别内存类型- 匿名内存 vs 文件映射检查地址范围- 确保目标地址在有效 VMA 内查找内存空洞- VMA 之间的未映射区域使用自动化工具- 编写脚本简化分析流程VMA何时创建的文章请参考linux VMA创建场景详解。