You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

当mmap()请求映射尺寸大于文件时的预期行为探究

mmap映射超出文件大小区域的行为分析

用户给出的mmap使用示例:

// 假设 PAGE_SIZE == 4096
int fd = open("/some/large/resource", O_RDONLY);
void *buffer = mmap(NULL, 8192, PROT_READ, MAP_SHARED, fd, 0);
// 使用buffer
munmap(buffer, 8192);

对应的read实现示例:

int fd = open("/some/large/resource", O_RDONLY);
void *buffer = malloc(8196);
read(fd, buffer, 8196);
// 使用buffer
free(buffer);

当前场景:目标文件/some/large/resource实际大小为4096字节(一页),但mmap尝试映射8192字节(两页),以下分析两种方式的差异及mmap不同flag下的行为:

read方式的表现

调用read后,会返回实际读取的4096字节,malloc分配的缓冲区中未被填充的剩余部分(4096-8195字节)是未初始化内存,值不确定,但可正常写入。

mmap的行为(按flag分类)

MAP_SHARED 模式

  • mmap调用本身不会报错,内核允许创建超出文件大小的映射区域。
  • 当访问超出文件大小的那一页(即4096-8191字节范围)时,会触发SIGBUS信号,直接导致程序崩溃。原因是MAP_SHARED要求映射区域与原文件同步,但原文件以O_RDONLY打开,无法扩展来容纳超出的页,内核无法完成映射页与文件的关联,因此触发总线错误。

MAP_PRIVATE 模式

  • mmap调用同样不会报错。
  • 访问超出文件大小的那一页时,内核会自动分配一块私有匿名页,并将其初始化为0。此时读取这部分内存会得到全0值;如果映射时设置了PROT_WRITE权限,写入这部分只会修改私有页,不会影响原文件。

核心差异总结

  • 映射超出文件大小的区域时,mmap本身不会失败,行为差异体现在实际访问超出区域时。
  • MAP_SHARED下访问超出区域(只读文件场景)会触发SIGBUS;MAP_PRIVATE下会得到初始化为0的私有页,可安全访问。
  • 与read方式的区别:read的剩余缓冲区是未初始化的垃圾值,而mmap在MAP_PRIVATE下超出部分是0,MAP_SHARED下直接触发错误。

内容的提问来源于stack exchange,提问作者CPlus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 22:12:30