mmap 异常通常由参数误用、资源限制、内存布局冲突或内核配置引起,需检查返回值与 errno、/proc/pid/maps 布局、文件约束及系统限制(如 max_map_count、overcommit_memory)。

Linux 中 mmap 调用失败或映射行为异常(如访问段错误、数据不一致、权限不符、地址冲突等),通常不是随机发生,而是由参数误用、资源限制、内存布局冲突或内核配置引起。排查需从调用上下文、系统状态和内核日志三方面入手。
检查 mmap 返回值与 errno
mmap失败时返回MAP_FAILED(即(void *)-1),必须立即检查errno,这是最直接的线索:
-
ENOMEM:常见但含义多样——可能是虚拟地址空间不足(32 位进程易触发)、RLIMIT_AS/RLIMIT_DATA 超限、或系统整体内存 +swap 耗尽; -
EACCES:文件映射时权限不足(如 O_RDONLY 文件却用 PROT_WRITE);或尝试 MAP_PRIVATE+PROT_WRITE 映射只读设备(如某些 proc/sysfs 节点); -
EINVAL:参数非法——offset 非页对齐、len 为 0、addr 非 NULL 但未按页对齐且未设 MAP_FIXED、flags 与 prot 冲突(如 MAP_SHARED+PROT_WRITE 映射不可写文件); -
EBADF:传入了无效 fd(已关闭、非映射支持类型,如普通管道 fd); -
EPERM:尝试 MAP_LOCKED 但无 CAP_IPC_LOCK 能力,或内核禁用大页锁定。
确认虚拟内存布局与地址冲突
使用 /proc/PID/maps 观察进程当前映射区域,重点排查:
- 是否在指定
addr处已有其他映射(尤其是设置了MAP_FIXED却未先munmap); - 是否存在大量匿名映射碎片,导致大块连续地址无法分配(
cat /proc/PID/status | grep VmPeak看峰值虚拟内存); - 32 位进程注意用户空间上限(通常 3GB),
brk堆顶与栈底接近时,mmap可能因找不到足够间隙而失败。
调试技巧:临时去掉 MAP_FIXED,让内核自主选址;或用strace -e trace=mmap,munmap 捕获实际调用参数与返回值。
验证文件映射相关约束
对文件映射(fd != -1),需额外检查:
- 文件是否被截断或删除:映射后原文件被
truncate()或unlink(),不会立即影响映射,但后续msync(MS_SYNC)可能失败,读写行为依映射类型而异; - 文件系统是否支持 mmap:某些网络文件系统(NFSv3 早期版本)、tmpfs 特殊挂载选项下可能拒绝写时复制(COW);
- 偏移量
offset必须是页对齐(getpagesize()),否则EINVAL; -
MAP_SHARED映射修改后需msync确保落盘,否则依赖文件系统策略,可能丢失。
关注系统级限制与内核配置
运行时限制和内核参数直接影响 mmap 行为:
- 检查
ulimit -v(RLIMIT_AS)、ulimit -d(RLIMIT_DATA),过严会直接触发ENOMEM; -
/proc/sys/vm/max_map_count:单进程最大 mmap 区域数,默认 65530,映射过多小区域(如每个共享库一个)可能触顶,报ENOMEM; -
/proc/sys/vm/overcommit_memory:设为 2 时严格检查可用内存 +swap,物理内存紧张时mmap更易失败; - dmesg 中搜索 ”mmap” 或 ”out of memory”,确认是否触发 OOM killer 或内核拒绝分配。
不复杂但容易忽略






























