云计算百科
云计算领域专业知识百科平台

Linux6.19-ARM64 mm mmap子模块深入分析

文章目录

  • 1. 概述
  • 2. 软件架构图
  • 3. 调用流程图
  • 4. UML类图
  • 5. 源码深度分析
    • 5.1 ARM64内存映射架构分析
      • 5.1.1 mmap系统调用实现
      • 5.1.2 地址空间分配
    • 5.2 内存映射建立分析
      • 5.2.1 VMA创建和管理
      • 5.2.2 文件映射处理
    • 5.3 映射类型和权限管理分析
      • 5.3.1 映射类型处理
      • 5.3.2 安全和权限验证
  • 6. 设计模式分析
    • 6.1 策略模式在映射类型选择中的体现
    • 6.2 工厂模式在VMA创建中的体现
    • 6.3 观察者模式在映射监控中的体现
  • 7. 状态机分析
  • 8. 性能优化分析
    • 8.1 地址分配优化
    • 8.2 映射预热优化
  • 9. 安全性考虑
    • 9.1 映射权限安全验证
    • 9.2 地址空间隔离保护
  • 10. 扩展性分析
    • 10.1 多架构支持
    • 10.2 功能扩展
  • 11. 调试和维护
    • 11.1 mmap调试支持
    • 11.2 错误检测和恢复
  • 12. 总结

  团队博客: 汽车电子社区


1. 概述

  ARM64 mm mmap子模块是Linux内核ARM64架构内存管理子系统中实现内存映射管理的核心组件,包含mmap.c文件。该模块作为ARM64平台虚拟内存映射的关键实现,提供了完整的地址空间管理、内存映射建立、文件映射支持和共享内存机制,是用户空间和内核空间内存交互的桥梁。

  mmap子模块实现了Linux虚拟内存系统的核心抽象,包括匿名映射、文件映射、共享映射、私有映射等各种映射类型的支持。该模块作为系统调用的核心实现,为应用程序提供了统一的内存访问接口,支持动态内存分配、大文件映射、进程间通信等关键功能,是现代操作系统内存管理的重要组成部分。

  模块的设计体现了内存映射管理的复杂性和灵活性要求,通过精心设计的映射算法和权限控制机制,在保证内存访问安全性的同时实现了高效的虚拟内存管理,是ARM64内存子系统用户接口的核心。

2. 软件架构图

#mermaid-svg-hmOMsHcgBhIofaJj{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hmOMsHcgBhIofaJj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hmOMsHcgBhIofaJj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hmOMsHcgBhIofaJj .error-icon{fill:#552222;}#mermaid-svg-hmOMsHcgBhIofaJj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hmOMsHcgBhIofaJj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hmOMsHcgBhIofaJj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hmOMsHcgBhIofaJj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hmOMsHcgBhIofaJj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hmOMsHcgBhIofaJj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hmOMsHcgBhIofaJj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hmOMsHcgBhIofaJj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hmOMsHcgBhIofaJj .marker.cross{stroke:#333333;}#mermaid-svg-hmOMsHcgBhIofaJj svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hmOMsHcgBhIofaJj p{margin:0;}#mermaid-svg-hmOMsHcgBhIofaJj .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-hmOMsHcgBhIofaJj .cluster-label text{fill:#333;}#mermaid-svg-hmOMsHcgBhIofaJj .cluster-label span{color:#333;}#mermaid-svg-hmOMsHcgBhIofaJj .cluster-label span p{background-color:transparent;}#mermaid-svg-hmOMsHcgBhIofaJj .label text,#mermaid-svg-hmOMsHcgBhIofaJj span{fill:#333;color:#333;}#mermaid-svg-hmOMsHcgBhIofaJj .node rect,#mermaid-svg-hmOMsHcgBhIofaJj .node circle,#mermaid-svg-hmOMsHcgBhIofaJj .node ellipse,#mermaid-svg-hmOMsHcgBhIofaJj .node polygon,#mermaid-svg-hmOMsHcgBhIofaJj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hmOMsHcgBhIofaJj .rough-node .label text,#mermaid-svg-hmOMsHcgBhIofaJj .node .label text,#mermaid-svg-hmOMsHcgBhIofaJj .image-shape .label,#mermaid-svg-hmOMsHcgBhIofaJj .icon-shape .label{text-anchor:middle;}#mermaid-svg-hmOMsHcgBhIofaJj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hmOMsHcgBhIofaJj .rough-node .label,#mermaid-svg-hmOMsHcgBhIofaJj .node .label,#mermaid-svg-hmOMsHcgBhIofaJj .image-shape .label,#mermaid-svg-hmOMsHcgBhIofaJj .icon-shape .label{text-align:center;}#mermaid-svg-hmOMsHcgBhIofaJj .node.clickable{cursor:pointer;}#mermaid-svg-hmOMsHcgBhIofaJj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hmOMsHcgBhIofaJj .arrowheadPath{fill:#333333;}#mermaid-svg-hmOMsHcgBhIofaJj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hmOMsHcgBhIofaJj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hmOMsHcgBhIofaJj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hmOMsHcgBhIofaJj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hmOMsHcgBhIofaJj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hmOMsHcgBhIofaJj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hmOMsHcgBhIofaJj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hmOMsHcgBhIofaJj .cluster text{fill:#333;}#mermaid-svg-hmOMsHcgBhIofaJj .cluster span{color:#333;}#mermaid-svg-hmOMsHcgBhIofaJj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hmOMsHcgBhIofaJj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hmOMsHcgBhIofaJj rect.text{fill:none;stroke-width:0;}#mermaid-svg-hmOMsHcgBhIofaJj .icon-shape,#mermaid-svg-hmOMsHcgBhIofaJj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hmOMsHcgBhIofaJj .icon-shape p,#mermaid-svg-hmOMsHcgBhIofaJj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hmOMsHcgBhIofaJj .icon-shape rect,#mermaid-svg-hmOMsHcgBhIofaJj .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hmOMsHcgBhIofaJj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hmOMsHcgBhIofaJj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hmOMsHcgBhIofaJj :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

ARM64 mm mmap

内存映射管理

地址空间分配

映射类型支持

权限控制机制

mmap.c

虚拟地址分配

物理内存映射

映射关系维护

VMA管理

地址空间布局

内存区域合并

匿名映射

文件映射

共享映射

访问权限控制

映射属性设置

安全验证

3. 调用流程图

#mermaid-svg-uHVy42BMoU0Y1KQM{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uHVy42BMoU0Y1KQM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uHVy42BMoU0Y1KQM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uHVy42BMoU0Y1KQM .error-icon{fill:#552222;}#mermaid-svg-uHVy42BMoU0Y1KQM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uHVy42BMoU0Y1KQM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uHVy42BMoU0Y1KQM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uHVy42BMoU0Y1KQM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uHVy42BMoU0Y1KQM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uHVy42BMoU0Y1KQM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uHVy42BMoU0Y1KQM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uHVy42BMoU0Y1KQM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uHVy42BMoU0Y1KQM .marker.cross{stroke:#333333;}#mermaid-svg-uHVy42BMoU0Y1KQM svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uHVy42BMoU0Y1KQM p{margin:0;}#mermaid-svg-uHVy42BMoU0Y1KQM .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-uHVy42BMoU0Y1KQM .cluster-label text{fill:#333;}#mermaid-svg-uHVy42BMoU0Y1KQM .cluster-label span{color:#333;}#mermaid-svg-uHVy42BMoU0Y1KQM .cluster-label span p{background-color:transparent;}#mermaid-svg-uHVy42BMoU0Y1KQM .label text,#mermaid-svg-uHVy42BMoU0Y1KQM span{fill:#333;color:#333;}#mermaid-svg-uHVy42BMoU0Y1KQM .node rect,#mermaid-svg-uHVy42BMoU0Y1KQM .node circle,#mermaid-svg-uHVy42BMoU0Y1KQM .node ellipse,#mermaid-svg-uHVy42BMoU0Y1KQM .node polygon,#mermaid-svg-uHVy42BMoU0Y1KQM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uHVy42BMoU0Y1KQM .rough-node .label text,#mermaid-svg-uHVy42BMoU0Y1KQM .node .label text,#mermaid-svg-uHVy42BMoU0Y1KQM .image-shape .label,#mermaid-svg-uHVy42BMoU0Y1KQM .icon-shape .label{text-anchor:middle;}#mermaid-svg-uHVy42BMoU0Y1KQM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uHVy42BMoU0Y1KQM .rough-node .label,#mermaid-svg-uHVy42BMoU0Y1KQM .node .label,#mermaid-svg-uHVy42BMoU0Y1KQM .image-shape .label,#mermaid-svg-uHVy42BMoU0Y1KQM .icon-shape .label{text-align:center;}#mermaid-svg-uHVy42BMoU0Y1KQM .node.clickable{cursor:pointer;}#mermaid-svg-uHVy42BMoU0Y1KQM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uHVy42BMoU0Y1KQM .arrowheadPath{fill:#333333;}#mermaid-svg-uHVy42BMoU0Y1KQM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uHVy42BMoU0Y1KQM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uHVy42BMoU0Y1KQM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uHVy42BMoU0Y1KQM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uHVy42BMoU0Y1KQM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uHVy42BMoU0Y1KQM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uHVy42BMoU0Y1KQM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uHVy42BMoU0Y1KQM .cluster text{fill:#333;}#mermaid-svg-uHVy42BMoU0Y1KQM .cluster span{color:#333;}#mermaid-svg-uHVy42BMoU0Y1KQM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uHVy42BMoU0Y1KQM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uHVy42BMoU0Y1KQM rect.text{fill:none;stroke-width:0;}#mermaid-svg-uHVy42BMoU0Y1KQM .icon-shape,#mermaid-svg-uHVy42BMoU0Y1KQM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uHVy42BMoU0Y1KQM .icon-shape p,#mermaid-svg-uHVy42BMoU0Y1KQM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uHVy42BMoU0Y1KQM .icon-shape rect,#mermaid-svg-uHVy42BMoU0Y1KQM .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uHVy42BMoU0Y1KQM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uHVy42BMoU0Y1KQM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uHVy42BMoU0Y1KQM :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

应用程序调用mmap

系统调用处理

参数验证

参数有效?

返回错误

查找空闲地址空间

找到合适地址?

返回ENOMEM

创建VMA结构

设置映射属性

建立映射关系

文件映射?

关联文件对象

匿名映射处理

设置页缓存

更新地址空间

返回映射地址

结束

4. UML类图

#mermaid-svg-U3Nbi08WJWio9y3O{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-U3Nbi08WJWio9y3O .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-U3Nbi08WJWio9y3O .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-U3Nbi08WJWio9y3O .error-icon{fill:#552222;}#mermaid-svg-U3Nbi08WJWio9y3O .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-U3Nbi08WJWio9y3O .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-U3Nbi08WJWio9y3O .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-U3Nbi08WJWio9y3O .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-U3Nbi08WJWio9y3O .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-U3Nbi08WJWio9y3O .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-U3Nbi08WJWio9y3O .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-U3Nbi08WJWio9y3O .marker{fill:#333333;stroke:#333333;}#mermaid-svg-U3Nbi08WJWio9y3O .marker.cross{stroke:#333333;}#mermaid-svg-U3Nbi08WJWio9y3O svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-U3Nbi08WJWio9y3O p{margin:0;}#mermaid-svg-U3Nbi08WJWio9y3O g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-U3Nbi08WJWio9y3O g.classGroup text .title{font-weight:bolder;}#mermaid-svg-U3Nbi08WJWio9y3O .nodeLabel,#mermaid-svg-U3Nbi08WJWio9y3O .edgeLabel{color:#131300;}#mermaid-svg-U3Nbi08WJWio9y3O .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-U3Nbi08WJWio9y3O .label text{fill:#131300;}#mermaid-svg-U3Nbi08WJWio9y3O .labelBkg{background:#ECECFF;}#mermaid-svg-U3Nbi08WJWio9y3O .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-U3Nbi08WJWio9y3O .classTitle{font-weight:bolder;}#mermaid-svg-U3Nbi08WJWio9y3O .node rect,#mermaid-svg-U3Nbi08WJWio9y3O .node circle,#mermaid-svg-U3Nbi08WJWio9y3O .node ellipse,#mermaid-svg-U3Nbi08WJWio9y3O .node polygon,#mermaid-svg-U3Nbi08WJWio9y3O .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-U3Nbi08WJWio9y3O .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O g.clickable{cursor:pointer;}#mermaid-svg-U3Nbi08WJWio9y3O g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-U3Nbi08WJWio9y3O g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-U3Nbi08WJWio9y3O .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-U3Nbi08WJWio9y3O .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-U3Nbi08WJWio9y3O .dashed-line{stroke-dasharray:3;}#mermaid-svg-U3Nbi08WJWio9y3O .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-U3Nbi08WJWio9y3O #compositionStart,#mermaid-svg-U3Nbi08WJWio9y3O .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O #compositionEnd,#mermaid-svg-U3Nbi08WJWio9y3O .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O #dependencyStart,#mermaid-svg-U3Nbi08WJWio9y3O .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O #dependencyStart,#mermaid-svg-U3Nbi08WJWio9y3O .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O #extensionStart,#mermaid-svg-U3Nbi08WJWio9y3O .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O #extensionEnd,#mermaid-svg-U3Nbi08WJWio9y3O .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O #aggregationStart,#mermaid-svg-U3Nbi08WJWio9y3O .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O #aggregationEnd,#mermaid-svg-U3Nbi08WJWio9y3O .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O #lollipopStart,#mermaid-svg-U3Nbi08WJWio9y3O .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O #lollipopEnd,#mermaid-svg-U3Nbi08WJWio9y3O .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U3Nbi08WJWio9y3O .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-U3Nbi08WJWio9y3O .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-U3Nbi08WJWio9y3O .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-U3Nbi08WJWio9y3O .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-U3Nbi08WJWio9y3O :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

MmapManager

+do_mmap()

+vm_mmap_pgoff()

+get_unmapped_area()

+mmap_region()

+insert_vm_struct()

VMAAllocator

+find_vma()

+get_unmapped_area()

+arch_get_unmapped_area()

+vm_unmapped_area()

+thp_get_unmapped_area()

MappingHandler

+file_mmap()

+generic_file_mmap()

+mmap_region()

+remap_pfn_range()

+vm_iomap_memory()

PermissionManager

+may_expand_vm()

+security_mmap_addr()

+validate_mmap_request()

+check_mmap_permissions()

VMAManager

+vma_merge()

+split_vma()

+insert_vm_struct()

+remove_vma()

+find_vma_intersection()

AddressSpaceManager

+expand_downwards()

+expand_upwards()

+arch_unmapped_area()

+unmapped_area()

+unmapped_area_topdown()

MemoryRegion

+vm_area_struct

+vm_start

+vm_end

+vm_flags

+vm_file

+vm_pgoff

FileMapping

+file->f_op->mmap()

+generic_file_mmap()

+mmap_region()

+setup_mapping()

5. 源码深度分析

5.1 ARM64内存映射架构分析

5.1.1 mmap系统调用实现

  ARM64 mmap系统调用的核心实现:

// ARM64 mmap系统调用主函数
SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags,
unsigned long, fd, unsigned long, off)
{
// 参数验证
if (unlikely((prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM)) != 0))
return EINVAL;

if (unlikely((flags & MAP_HUGE_MASK) != 0 && (flags & MAP_HUGE_MASK) != MAP_HUGE_2MB &&
(flags & MAP_HUGE_MASK) != MAP_HUGE_1GB))
return EINVAL;

// 长度检查
if (unlikely(len == 0))
return addr;

if (unlikely(len > TASK_SIZE PAGE_SIZE))
return ENOMEM;

// 地址对齐检查
if (unlikely((flags & MAP_FIXED) && (addr & ~PAGE_MASK)))
return EINVAL;

// 权限检查
if (unlikely(!access_ok(addr, len)))
return EFAULT;

// 调用核心mmap函数
return ksys_mmap_pgoff(addr, len, prot, flags, fd,
off >> PAGE_SHIFT);
}

// mmap核心实现函数
unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
struct file *file = NULL;
unsigned long retval;

// 获取文件对象
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
return EBADF;
}

// 执行mmap操作
retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);

// 释放文件引用
if (file)
fput(file);

return retval;
}

// 虚拟内存映射核心函数
unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flags, unsigned long pgoff)
{
unsigned long ret;
struct mm_struct *mm = current->mm;

// 地址空间锁定
down_write(&mm->mmap_sem);

// 执行映射
ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff, &populate);

// 地址空间解锁
up_write(&mm->mmap_sem);

// 页面填充(如果需要)
if (!ret && populate)
mm_populate(ret, len, populate);

return ret;
}

  mmap系统调用特点:

    1. 参数验证:严格的参数检查和权限验证     2. 文件处理:文件描述符到文件对象的转换     3. 地址空间同步:使用读写信号量保护地址空间     4. 页面填充:按需填充映射的页面

5.1.2 地址空间分配

  地址空间分配的核心算法:

// 获取未映射区域的函数
unsigned long get_unmapped_area(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags)
{
unsigned long (*get_area)(struct file *, unsigned long,
unsigned long, unsigned long, unsigned long);

// 选择合适的分配函数
get_area = current->mm->get_unmapped_area;
if (!get_area)
get_area = arch_get_unmapped_area;

// 如果指定了地址,尝试固定映射
if (flags & MAP_FIXED) {
addr = get_area(file, addr, len, pgoff, flags);
return addr;
}

// 尝试自顶向下分配
if (len > current->mm->mmap_base) {
addr = get_area(file, addr, len, pgoff, flags);
if (!IS_ERR_VALUE(addr))
return addr;
}

// 自底向上分配
addr = vm_unmapped_area(&current->mm->mm_rb, addr, len, pgoff, flags);
if (!(flags & MAP_FIXED) && addr & ~PAGE_MASK)
return vm_unmapped_area_topdown(&current->mm->mm_rb, addr, len, pgoff, flags);

return addr;
}

// 自底向上地址分配
unsigned long vm_unmapped_area(struct rb_root *root, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags)
{
struct mm_struct *mm = current->mm;
unsigned long start_addr;

// 确定起始地址
if (flags & MAP_FIXED)
start_addr = addr;
else if (addr) {
start_addr = addr;
if (start_addr & (shmlba 1))
start_addr &= ~(shmlba 1);
} else {
start_addr = mm->mmap_base;
}

// 查找合适的空闲区域
return unmapped_area(root, start_addr, len, 0, flags);
}

// 自顶向下地址分配
unsigned long unmapped_area_topdown(struct rb_root *root,
unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
{
struct mm_struct *mm = current->mm;
unsigned long start_addr;

// 从高地址开始分配
if (flags & MAP_FIXED)
start_addr = addr;
else {
start_addr = mm->free_area_cache;
if (start_addr & (shmlba 1))
start_addr &= ~(shmlba 1);
}

// 查找合适的空闲区域
return unmapped_area(root, start_addr, len, 1, flags);
}

  地址分配特点:

    1. 多种策略:自底向上和自顶向下两种分配策略     2. 固定映射:支持固定地址映射     3. 对齐处理:考虑共享内存对齐要求的处理     4. 缓存优化:使用free_area_cache优化查找性能

5.2 内存映射建立分析

5.2.1 VMA创建和管理

  虚拟内存区域创建的核心实现:

// 执行内存映射的核心函数
unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flags, unsigned long pgoff,
struct list_head *uf)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
unsigned long charged = 0;

// 验证参数
if (!len)
return EINVAL;

// 计算页面数量
len = PAGE_ALIGN(len);
if (!len)
return ENOMEM;

// 获取未映射区域
addr = get_unmapped_area(file, addr, len, pgoff, flags);
if (IS_ERR_VALUE(addr))
return addr;

// 检查RLIMIT_AS限制
if (!may_expand_vm(mm, len >> PAGE_SHIFT))
return ENOMEM;

// 为文件映射预充电
if (file && !(flags & MAP_ANONYMOUS)) {
if (vm_mmap_pgoff_charge(mm, len, flags))
return ENOMEM;
charged = len;
}

// 创建VMA
vma = vm_area_alloc(mm);
if (!vma) {
if (charged)
vm_mmap_pgoff_uncharge(mm, charged);
return ENOMEM;
}

// 初始化VMA
vma->vm_start = addr;
vma->vm_end = addr + len;
vma->vm_flags = calc_vm_prot_bits(prot, flags) |
calc_vm_flag_bits(flags) |
mm->def_flags |
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;

if (file) {
vma->vm_file = get_file(file);
vma->vm_pgoff = pgoff;
error = call_mmap(file, vma);
addr = error;
} else if (flags & MAP_SHARED) {
error = shmem_zero_setup(vma);
if (error) {
vm_area_free(vma);
if (charged)
vm_mmap_pgoff_uncharge(mm, charged);
return error;
}
}

// 插入VMA到地址空间
if (mmap_region(file, addr, len, flags, vma))
return addr;

// 映射失败,清理资源
if (charged)
vm_mmap_pgoff_uncharge(mm, charged);
vm_area_free(vma);
return ENOMEM;
}

// 映射区域建立
unsigned long mmap_region(struct file *file, unsigned long addr,
unsigned long len, unsigned long flags,
struct vm_area_struct *vma)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *prev, *next;

// 查找相邻VMA
prev = find_vma_prev(mm, addr, &next);

// 检查是否可以合并
if (prev && prev->vm_end == addr &&
can_vma_merge_after(prev, addr, next,
vma->vm_flags, NULL, file, pgoff)) {
// 扩展前一个VMA
prev->vm_end = addr + len;
prev->vm_flags |= vma->vm_flags;
vm_area_free(vma);
return addr;
}

// 插入新的VMA
if (insert_vm_struct(mm, vma)) {
vm_area_free(vma);
return ENOMEM;
}

return addr;
}

  VMA管理特点:

    1. 动态创建:按需创建虚拟内存区域     2. 参数初始化:完整的VMA属性设置     3. 文件关联:文件映射的文件对象关联     4. 区域合并:相邻VMA的智能合并优化

5.2.2 文件映射处理

  文件映射的核心处理逻辑:

// 文件mmap操作调用
int call_mmap(struct file *file, struct vm_area_struct *vma)
{
int (*mmap)(struct file *, struct vm_area_struct *);
int error = ENODEV;

// 获取文件的mmap操作
mmap = file->f_op->mmap;
if (mmap)
error = mmap(file, vma);

// 如果文件系统不支持,使用通用文件映射
if (error == ENODEV) {
error = generic_file_mmap(file, vma);
}

return error;
}

// 通用文件映射
int generic_file_mmap(struct file *file, struct vm_area_struct *vma)
{
struct address_space *mapping = file->f_mapping;

// 检查文件是否可映射
if (!mapping->a_ops->readpage)
return ENOEXEC;

// 设置VMA操作
vma->vm_ops = &generic_file_vm_ops;

// 对于可写映射,设置脏页跟踪
if (vma->vm_flags & VM_MAYWRITE) {
// 确保文件系统支持写操作
if (!mapping->a_ops->writepage)
return EINVAL;
}

// 对于共享可写映射,设置MS_INVALIDATE
if ((vma->vm_flags & (VM_MAYSHARE | VM_MAYWRITE)) == (VM_MAYSHARE | VM_MAYWRITE))
mapping->flags |= AS_MM_ALL_LOCKS;

return 0;
}

// mmap区域处理
int mmap_region(struct file *file, unsigned long addr,
unsigned long len, unsigned long flags,
struct vm_area_struct *vma)
{
struct mm_struct *mm = vma->vm_mm;
int error;

// 调用文件系统的mmap_region(如果支持)
if (file && file->f_op->mmap_region) {
error = file->f_op->mmap_region(file, vma, addr, len, flags);
if (!error)
goto out;
}

// 建立页表映射
error = remap_pfn_range(vma, addr, vma->vm_pgoff, len, vma->vm_page_prot);
if (error)
return error;

out:
// 更新统计信息
mm->total_vm += len >> PAGE_SHIFT;
if (flags & MAP_SHARED)
mm->shared_vm += len >> PAGE_SHIFT;
else
mm->anon_vm += len >> PAGE_SHIFT;

return 0;
}

  文件映射特点:

    1. 文件系统钩子:调用文件系统的mmap操作     2. 通用映射:不支持专用mmap的文件使用通用实现     3. 页表映射:建立虚拟地址到物理页面的映射     4. 统计更新:更新内存使用统计信息

5.3 映射类型和权限管理分析

5.3.1 映射类型处理

  不同映射类型的处理逻辑:

// 计算虚拟内存保护位
unsigned long calc_vm_prot_bits(unsigned long prot, unsigned long flags)
{
unsigned long vm_prot = 0;

// 设置基本权限
if (prot & PROT_READ)
vm_prot |= VM_READ;
if (prot & PROT_WRITE)
vm_prot |= VM_WRITE;
if (prot & PROT_EXEC)
vm_prot |= VM_EXEC;

// 处理特殊权限
if (prot & PROT_SEM)
vm_prot |= VM_SEM;

// ARM64特定的权限处理
if (IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN)) {
// PAN(Privileged Access Never)处理
if (!(flags & MAP_SHARED) && (prot & PROT_EXEC))
vm_prot |= VM_ARM64_BTI;
}

return vm_prot;
}

// 计算虚拟内存标志位
unsigned long calc_vm_flag_bits(unsigned long flags)
{
unsigned long vm_flags = 0;

// 映射类型标志
if (flags & MAP_SHARED)
vm_flags |= VM_SHARED;
else
vm_flags |= VM_PRIVATE;

// 其他标志
if (flags & MAP_FIXED)
vm_flags |= VM_FIXED;
if (flags & MAP_GROWSDOWN)
vm_flags |= VM_GROWSDOWN;
if (flags & MAP_GROWSUP)
vm_flags |= VM_GROWSUP;
if (flags & MAP_LOCKED)
vm_flags |= VM_LOCKED;
if (flags & MAP_HUGETLB)
vm_flags |= VM_HUGETLB;
if (flags & MAP_NONBLOCK)
vm_flags |= VM_NONBLOCK;
if (flags & MAP_NORESERVE)
vm_flags |= VM_NORESERVE;
if (flags & MAP_POPULATE)
vm_flags |= VM_POPULATE;

return vm_flags;
}

// 匿名映射处理
int shmem_zero_setup(struct vm_area_struct *vma)
{
struct file *file;
int error;

// 创建匿名文件
error = shmem_zero_setup_mapping(vma, vma->vm_start,
(vma->vm_end vma->vm_start) >> PAGE_SHIFT,
vma->vm_flags & VM_SHARED);
if (error)
return error;

// 获取文件对象
file = shmem_file_setup("dev/zero", 0, VM_SHARED);
if (IS_ERR(file))
return PTR_ERR(file);

// 设置VMA文件
vma->vm_file = file;
vma->vm_ops = &shmem_vm_ops;

return 0;
}

  映射类型特点:

    1. 权限转换:用户空间权限到内核VMA权限的转换     2. 标志处理:各种映射标志的正确设置     3. 匿名映射:使用共享内存实现匿名映射     4. 特殊处理:大页、锁定等特殊映射类型的处理

5.3.2 安全和权限验证

  映射操作的安全验证:

// mmap权限检查
int security_mmap_addr(unsigned long addr)
{
// 安全模块检查地址
return security_mmap_addr_hook(addr);
}

// 验证mmap请求
int validate_mmap_request(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flags, unsigned long pgoff)
{
// 检查地址范围
if (unlikely(addr > TASK_SIZE len))
return EINVAL;

// 检查长度限制
if (unlikely(len > TASK_SIZE || len == 0))
return EINVAL;

// 检查对齐
if (unlikely(addr & ~PAGE_MASK))
return EINVAL;

// 检查权限组合的有效性
if (unlikely((prot & PROT_WRITE) && !(file || (flags & MAP_ANONYMOUS))))
return EACCES;

// 检查共享映射的权限
if (unlikely((flags & MAP_SHARED) && (prot & PROT_WRITE) &&
(!file || !(file->f_mode & FMODE_WRITE))))
return EACCES;

return 0;
}

// 虚拟内存扩展检查
int may_expand_vm(struct mm_struct *mm, unsigned long npages)
{
unsigned long cur = mm->total_vm;
unsigned long lim;

// 检查RLIMIT_AS限制
lim = rlimit(RLIMIT_AS) >> PAGE_SHIFT;
if (cur + npages > lim)
return 0;

// 检查系统限制
if (mm->total_vm + npages > sysctl_max_map_count)
return 0;

return 1;
}

  安全验证特点:

    1. 地址验证:地址范围和对齐的检查     2. 权限验证:文件访问权限的验证     3. 资源限制:系统资源使用限制的检查     4. 安全钩子:安全模块的权限检查

6. 设计模式分析

6.1 策略模式在映射类型选择中的体现

  映射类型选择的策略模式:

// 映射策略接口
interface MappingStrategy {
int map(MemoryRegion region, MappingRequest request);
boolean canHandle(MappingRequest request);
String getStrategyName();
double getMappingEfficiency();
boolean supportsLazyAllocation();
}

// 匿名映射策略
class AnonymousMappingStrategy implements MappingStrategy {
public int map(MemoryRegion region, MappingRequest request) {
// 匿名映射实现
return shmem_zero_setup(region);
}

public boolean canHandle(MappingRequest request) {
return request.isAnonymous();
}

public String getStrategyName() {
return "ANONYMOUS_MAPPING";
}

public double getMappingEfficiency() {
return 0.95;
}

public boolean supportsLazyAllocation() {
return true;
}
}

// 文件映射策略
class FileMappingStrategy implements MappingStrategy {
public int map(MemoryRegion region, MappingRequest request) {
// 文件映射实现
return call_mmap(request.getFile(), region);
}

public boolean canHandle(MappingRequest request) {
return request.hasFile() && !request.isAnonymous();
}

public String getStrategyName() {
return "FILE_MAPPING";
}

public double getMappingEfficiency() {
return 0.90;
}

public boolean supportsLazyAllocation() {
return true;
}
}

// 设备映射策略
class DeviceMappingStrategy implements MappingStrategy {
public int map(MemoryRegion region, MappingRequest request) {
// 设备映射实现
return remap_pfn_range(region, region.getStart(),
request.getPfn(), region.getSize(),
region.getPageProt());
}

public boolean canHandle(MappingRequest request) {
return request.isDeviceMapping();
}

public String getStrategyName() {
return "DEVICE_MAPPING";
}

public double getMappingEfficiency() {
return 0.85;
}

public boolean supportsLazyAllocation() {
return false; // 设备映射通常需要预先分配
}
}

// 自适应映射策略
class AdaptiveMappingStrategy implements MappingStrategy {
private List<MappingStrategy> strategies;
private MappingStatistics stats;

public AdaptiveMappingStrategy() {
strategies = Arrays.asList(
new AnonymousMappingStrategy(),
new FileMappingStrategy(),
new DeviceMappingStrategy()
);
stats = new MappingStatistics();
}

public int map(MemoryRegion region, MappingRequest request) {
// 选择最适合的策略
MappingStrategy bestStrategy = selectBestStrategy(request);

long startTime = System.nanoTime();
int result = bestStrategy.map(region, request);
long mappingTime = System.nanoTime() startTime;

// 更新统计信息
stats.recordMapping(bestStrategy.getStrategyName(), result == 0, mappingTime);

return result;
}

public boolean canHandle(MappingRequest request) {
return strategies.stream().anyMatch(s -> s.canHandle(request));
}

public String getStrategyName() {
return "ADAPTIVE_MAPPING";
}

public double getMappingEfficiency() {
return stats.getOverallEfficiency();
}

public boolean supportsLazyAllocation() {
return true;
}

private MappingStrategy selectBestStrategy(MappingRequest request) {
return strategies.stream()
.filter(s -> s.canHandle(request))
.max(Comparator.comparingDouble(s -> calculateStrategyScore(s, request)))
.orElse(new AnonymousMappingStrategy());
}

private double calculateStrategyScore(MappingStrategy strategy, MappingRequest request) {
double efficiency = stats.getStrategyEfficiency(strategy.getStrategyName());
double lazyBonus = strategy.supportsLazyAllocation() && request.prefersLazy() ? 0.1 : 0.0;

return efficiency + lazyBonus;
}
}

// 策略选择器
class MappingStrategySelector {
public static MappingStrategy selectStrategy(MappingRequest request, SystemContext context) {
if (context.supportsAdaptiveMapping()) {
return new AdaptiveMappingStrategy();
} else if (request.isDeviceMapping()) {
return new DeviceMappingStrategy();
} else if (request.hasFile()) {
return new FileMappingStrategy();
} else {
return new AnonymousMappingStrategy();
}
}
}

6.2 工厂模式在VMA创建中的体现

  VMA创建的工厂模式:

// VMA工厂接口
interface VMAFactory {
VMAArea createVMA(MappingRequest request);
boolean canCreate(MappingRequest request);
String getFactoryName();
}

// 标准VMA工厂
class StandardVMAFactory implements VMAFactory {
public VMAArea createVMA(MappingRequest request) {
VMAArea vma = new VMAArea();

// 设置基本属性
vma.setStartAddress(request.getAddr());
vma.setSize(request.getLen());
vma.setProtection(request.getProt());
vma.setFlags(request.getFlags());

// 设置VMA操作
vma.setOperations(getStandardOperations(request));

return vma;
}

public boolean canCreate(MappingRequest request) {
return true; // 标准工厂可以处理所有请求
}

public String getFactoryName() {
return "STANDARD_VMA";
}

private VMAOperations getStandardOperations(MappingRequest request) {
if (request.isAnonymous()) {
return new AnonymousVMAOperations();
} else if (request.hasFile()) {
return new FileVMAOperations();
} else {
return new DefaultVMAOperations();
}
}
}

// 大页VMA工厂
class HugePageVMAFactory implements VMAFactory {
public VMAArea createVMA(MappingRequest request) {
VMAArea vma = new VMAArea();

// 设置大页属性
vma.setStartAddress(request.getAddr());
vma.setSize(alignToHugePageSize(request.getLen()));
vma.setProtection(request.getProt());
vma.setFlags(request.getFlags() | VM_HUGETLB);

// 设置大页操作
vma.setOperations(new HugePageVMAOperations());

return vma;
}

public boolean canCreate(MappingRequest request) {
// 检查是否支持大页且请求了大页
return systemSupportsHugePages() &&
(request.getFlags() & MAP_HUGETLB) != 0;
}

public String getFactoryName() {
return "HUGE_PAGE_VMA";
}

private long alignToHugePageSize(long size) {
long hugePageSize = getHugePageSize();
return (size + hugePageSize 1) & ~(hugePageSize 1);
}

private boolean systemSupportsHugePages() {
return isHugePageSupported();
}
}

// 固定映射VMA工厂
class FixedVMAFactory implements VMAFactory {
public VMAArea createVMA(MappingRequest request) {
VMAArea vma = new VMAArea();

// 固定地址映射
vma.setStartAddress(request.getAddr()); // 使用指定的固定地址
vma.setSize(request.getLen());
vma.setProtection(request.getProt());
vma.setFlags(request.getFlags() | VM_FIXED);

// 设置固定映射操作
vma.setOperations(new FixedVMAOperations());

return vma;
}

public boolean canCreate(MappingRequest request) {
// 检查是否为固定映射请求
return (request.getFlags() & MAP_FIXED) != 0;
}

public String getFactoryName() {
return "FIXED_VMA";
}
}

// VMA工厂管理器
class VMAFactoryManager {
private static List<VMAFactory> factories;

static {
factories = Arrays.asList(
new FixedVMAFactory(),
new HugePageVMAFactory(),
new StandardVMAFactory() // 标准工厂放在最后作为fallback
);
}

public static VMAArea createVMA(MappingRequest request) {
for (VMAFactory factory : factories) {
if (factory.canCreate(request)) {
return factory.createVMA(request);
}
}

throw new VMAFactoryException("No suitable factory found for request");
}

public static String getFactoryName(MappingRequest request) {
for (VMAFactory factory : factories) {
if (factory.canCreate(request)) {
return factory.getFactoryName();
}
}

return "UNKNOWN";
}
}

// 使用工厂模式
class MemoryMapper {
public VMAArea createMemoryMapping(MappingRequest request) {
// 使用工厂创建VMA
VMAArea vma = VMAFactoryManager.createVMA(request);

// 执行映射策略
MappingStrategy strategy = MappingStrategySelector.selectStrategy(
request, getSystemContext());

// 执行映射
int result = strategy.map(vma, request);
if (result != 0) {
throw new MappingException("Failed to map memory: " + result);
}

return vma;
}

private SystemContext getSystemContext() {
return new SystemContext(); // 获取当前系统上下文
}
}

6.3 观察者模式在映射监控中的体现

  映射监控的观察者模式:

// 映射事件接口
interface MappingEvent {
String getEventType();
long getTimestamp();
MemoryRegion getMappedRegion();
MappingRequest getOriginalRequest();
Map<String, Object> getEventData();
boolean isSuccess();
}

// 映射完成事件
class MappingCompleteEvent implements MappingEvent {
private final MemoryRegion region;
private final MappingRequest request;
private final boolean success;
private final Map<String, Object> eventData;

public MappingCompleteEvent(MemoryRegion region, MappingRequest request,
boolean success, Map<String, Object> eventData) {
this.region = region;
this.request = request;
this.success = success;
this.eventData = eventData != null ? eventData : new HashMap<>();
}

public String getEventType() {
return "MAPPING_COMPLETE";
}

public long getTimestamp() {
return System.nanoTime();
}

public MemoryRegion getMappedRegion() {
return region;
}

public MappingRequest getOriginalRequest() {
return request;
}

public Map<String, Object> getEventData() {
return eventData;
}

public boolean isSuccess() {
return success;
}
}

// 映射观察者接口
interface MappingObserver {
void onMappingEvent(MappingEvent event);
Set<String> getInterestedMappingTypes();
boolean isEnabled();
}

// 性能监控观察者
class MappingPerformanceObserver implements MappingObserver {
private Map<String, Long> mappingTimes = new HashMap<>();
private Map<String, Integer> mappingCounts = new HashMap<>();

public void onMappingEvent(MappingEvent event) {
String mappingType = determineMappingType(event.getOriginalRequest());

if ("MAPPING_COMPLETE".equals(event.getEventType())) {
// 记录映射时间
Long time = (Long) event.getEventData().get("mappingTime");
if (time != null) {
mappingTimes.put(mappingType,
mappingTimes.getOrDefault(mappingType, 0L) + time);
}

// 记录映射次数
mappingCounts.put(mappingType,
mappingCounts.getOrDefault(mappingType, 0) + 1);
}
}

public Set<String> getInterestedMappingTypes() {
return new HashSet<>(Arrays.asList("ANONYMOUS", "FILE", "DEVICE", "SHARED"));
}

public boolean isEnabled() {
return true;
}

private String determineMappingType(MappingRequest request) {
if (request.isAnonymous()) {
return "ANONYMOUS";
} else if (request.hasFile()) {
return request.isShared() ? "SHARED_FILE" : "PRIVATE_FILE";
} else {
return "DEVICE";
}
}

public double getAverageMappingTime(String mappingType) {
Long totalTime = mappingTimes.get(mappingType);
Integer count = mappingCounts.get(mappingType);

if (totalTime != null && count != null && count > 0) {
return totalTime.doubleValue() / count;
}
return 0.0;
}
}

// 内存使用观察者
class MemoryUsageObserver implements MappingObserver {
private AtomicLong totalMappedBytes = new AtomicLong(0);
private Map<String, AtomicLong> typeMappedBytes = new ConcurrentHashMap<>();

public void onMappingEvent(MappingEvent event) {
if (event.isSuccess()) {
long bytes = event.getMappedRegion().getSize();
totalMappedBytes.addAndGet(bytes);

String mappingType = determineMappingType(event.getOriginalRequest());
typeMappedBytes.computeIfAbsent(mappingType, k -> new AtomicLong(0))
.addAndGet(bytes);
}
}

public Set<String> getInterestedMappingTypes() {
return new HashSet<>(Arrays.asList("*")); // 监听所有类型
}

public boolean isEnabled() {
return true;
}

private String determineMappingType(MappingRequest request) {
if (request.isAnonymous()) {
return "ANONYMOUS";
} else if (request.hasFile()) {
return "FILE";
} else {
return "DEVICE";
}
}

public long getTotalMappedBytes() {
return totalMappedBytes.get();
}

public long getMappedBytesByType(String type) {
AtomicLong bytes = typeMappedBytes.get(type);
return bytes != null ? bytes.get() : 0;
}
}

// 安全监控观察者
class SecurityMappingObserver implements MappingObserver {
private List<String> securityEvents = Collections.synchronizedList(new ArrayList<>());

public void onMappingEvent(MappingEvent event) {
// 检查潜在的安全问题
MappingRequest request = event.getOriginalRequest();
MemoryRegion region = event.getMappedRegion();

// 检查可执行权限
if (region.isExecutable() && request.hasFile()) {
File file = request.getFile();
if (!isTrustedExecutable(file)) {
logSecurityEvent("Potentially unsafe executable mapping: " + file.getPath());
}
}

// 检查大页映射
if (region.isHugePage() && region.getSize() > MAX_SAFE_HUGE_PAGE_SIZE) {
logSecurityEvent("Large huge page mapping detected: " + region.getSize());
}

// 检查共享映射权限
if (request.isShared() && region.isWritable()) {
logSecurityEvent("Shared writable mapping: potential security risk");
}
}

public Set<String> getInterestedMappingTypes() {
return new HashSet<>(Arrays.asList("*"));
}

public boolean isEnabled() {
return true;
}

private void logSecurityEvent(String event) {
securityEvents.add(event);
// 记录到系统日志
System.err.println("SECURITY: " + event);
}

private boolean isTrustedExecutable(File file) {
// 检查文件是否来自可信来源
return file.isFromTrustedPath() || file.hasValidSignature();
}

public List<String> getSecurityEvents() {
return new ArrayList<>(securityEvents);
}
}

// 映射监控器
class MappingMonitor {
private List<MappingObserver> observers = new CopyOnWriteArrayList<>();
private Executor notificationExecutor;

public MappingMonitor() {
this.notificationExecutor = Executors.newSingleThreadExecutor();
}

public void addObserver(MappingObserver observer) {
observers.add(observer);
}

public void removeObserver(MappingObserver observer) {
observers.remove(observer);
}

public void notifyMappingEvent(MappingEvent event) {
notificationExecutor.submit(() -> {
for (MappingObserver observer : observers) {
if (observer.isEnabled()) {
Set<String> interestedTypes = observer.getInterestedMappingTypes();
String mappingType = determineMappingType(event.getOriginalRequest());

if (interestedTypes.contains("*") || interestedTypes.contains(mappingType)) {
try {
observer.onMappingEvent(event);
} catch (Exception e) {
logObserverError(observer, event, e);
}
}
}
}
});
}

public void startMapping(MappingRequest request) {
// 可以在这里添加映射开始事件
}

public void completeMapping(MemoryRegion region, MappingRequest request,
boolean success, Map<String, Object> eventData) {
MappingEvent event = new MappingCompleteEvent(region, request, success, eventData);
notifyMappingEvent(event);
}

public void shutdown() {
notificationExecutor.shutdown();
try {
if (!notificationExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
notificationExecutor.shutdownNow();
}
} catch (InterruptedException e) {
notificationExecutor.shutdownNow();
}
}

private String determineMappingType(MappingRequest request) {
if (request.isAnonymous()) {
return "ANONYMOUS";
} else if (request.hasFile()) {
return "FILE";
} else {
return "DEVICE";
}
}

private void logObserverError(MappingObserver observer, MappingEvent event, Exception e) {
System.err.println("Mapping observer error: " + observer.getClass().getSimpleName() +
" failed to process event " + event.getEventType() + ": " + e.getMessage());
}
}

// 使用观察者模式
class MemoryMappingSystem {
private MappingMonitor monitor;

public MemoryMappingSystem() {
this.monitor = new MappingMonitor();

// 注册观察者
monitor.addObserver(new MappingPerformanceObserver());
monitor.addObserver(new MemoryUsageObserver());
monitor.addObserver(new SecurityMappingObserver());
}

public MemoryRegion createMapping(MappingRequest request) {
monitor.startMapping(request);

long startTime = System.nanoTime();

try {
// 创建VMA
VMAArea vma = VMAFactoryManager.createVMA(request);

// 执行映射
MappingStrategy strategy = MappingStrategySelector.selectStrategy(
request, getSystemContext());

int result = strategy.map(vma, request);

long mappingTime = System.nanoTime() startTime;

// 通知映射完成
Map<String, Object> eventData = new HashMap<>();
eventData.put("mappingTime", mappingTime);
eventData.put("strategy", strategy.getStrategyName());

monitor.completeMapping(vma, request, result == 0, eventData);

if (result != 0) {
throw new MappingException("Mapping failed: " + result);
}

return vma;

} catch (Exception e) {
// 通知映射失败
Map<String, Object> errorData = new HashMap<>();
errorData.put("error", e.getMessage());
errorData.put("mappingTime", System.nanoTime() startTime);

monitor.completeMapping(null, request, false, errorData);
throw e;
}
}

private SystemContext getSystemContext() {
return new SystemContext(); // 获取当前系统上下文
}
}

7. 状态机分析

  ARM64 mm mmap的状态机:

初始状态 -> 请求验证 -> 地址分配 -> VMA创建 -> 映射策略选择 -> 权限设置 -> 页表建立 -> TLB更新 -> 映射完成
↑ ↓
参数检查 <——————————————————————————————————+
↑ ↓
安全验证 <——————————————————————————————————+
↑ ↓
资源分配 <——————————————————————————————————+

8. 性能优化分析

8.1 地址分配优化

  地址分配的性能优化:

// 地址分配缓存优化
static unsigned long cached_unmapped_area(struct rb_root *root,
unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
{
struct mm_struct *mm = current->mm;

// 检查缓存是否有效
if (mm->free_area_cache && mm->free_area_cache <= addr + len) {
unsigned long cached_addr = mm->free_area_cache;

// 验证缓存的地址是否仍然可用
if (is_area_available(root, cached_addr, len)) {
mm->free_area_cache = cached_addr + len;
return cached_addr;
}
}

// 缓存无效,执行正常分配
unsigned long new_addr = unmapped_area(root, addr, len, pgoff, flags);

// 更新缓存
if (!(flags & MAP_FIXED)) {
mm->free_area_cache = new_addr + len;
}

return new_addr;
}

// VMA查找优化
struct vm_area_struct *find_vma_prev(struct mm_struct *mm, unsigned long addr,
struct vm_area_struct **pprev)
{
struct vm_area_struct *vma = NULL, *prev = NULL;

// 使用红黑树进行快速查找
struct rb_node *rb_node = mm->mm_rb.rb_node;

while (rb_node) {
struct vm_area_struct *tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb);

if (tmp->vm_end > addr) {
rb_node = rb_node->rb_left;
vma = tmp;
if (pprev)
*pprev = prev;
} else {
rb_node = rb_node->rb_right;
prev = tmp;
}
}

// 更新查找缓存
if (vma)
mm->mmap_cache = vma;

if (pprev)
*pprev = prev;

return vma;
}

8.2 映射预热优化

  映射预热的性能优化:

// 映射预热优化
void mmap_prefault(struct vm_area_struct *vma, unsigned long start, size_t len)
{
unsigned long addr = start;
unsigned long end = start + len;

// 对于私有映射,预先分配页面
if (!(vma->vm_flags & VM_SHARED)) {
for (; addr < end; addr += PAGE_SIZE) {
// 预先触发页面错误
handle_mm_fault(vma, addr, FAULT_FLAG_WRITE, NULL);
}
}
}

// 批量映射优化
int mmap_batch(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot, unsigned long flags,
unsigned long pgoff, int batch_size)
{
unsigned long current_addr = addr;
unsigned long end_addr = addr + len;
int total_mapped = 0;

// 批量处理映射请求
while (current_addr < end_addr) {
unsigned long batch_len = min((unsigned long)batch_size * PAGE_SIZE,
end_addr current_addr);

// 执行批次映射
unsigned long mapped_addr = do_mmap_pgoff(file, current_addr, batch_len,
prot, flags, pgoff, NULL);

if (IS_ERR_VALUE(mapped_addr))
break;

current_addr += batch_len;
pgoff += batch_len >> PAGE_SHIFT;
total_mapped += batch_len;
}

return total_mapped;
}

9. 安全性考虑

9.1 映射权限安全验证

  映射权限的安全验证:

// 映射权限安全检查
int validate_mapping_permissions(struct file *file, unsigned long prot,
unsigned long flags, struct cred *cred)
{
// 检查文件访问权限
if (file) {
int access = 0;

if (prot & PROT_READ)
access |= MAY_READ;
if (prot & PROT_WRITE)
access |= MAY_WRITE;
if (prot & PROT_EXEC)
access |= MAY_EXEC;

// 执行文件权限检查
if (file_permission(file, access))
return EACCES;

// 检查文件是否允许mmap
if (!file->f_op->mmap)
return ENODEV;
}

// 检查映射类型安全
if ((flags & MAP_SHARED) && (prot & PROT_WRITE)) {
// 共享可写映射需要额外检查
if (file && !may_share_write_access(file, cred))
return EACCES;
}

// 检查可执行映射的安全性
if (prot & PROT_EXEC) {
if (!may_map_executable(cred))
return EACCES;
}

return 0;
}

// 共享写访问权限检查
static bool may_share_write_access(struct file *file, struct cred *cred)
{
// 检查文件系统是否允许共享写访问
if (file->f_path.mnt->mnt_flags & MNT_NOATIME)
return false;

// 检查文件权限
if (!(file->f_mode & FMODE_WRITE))
return false;

// 检查凭据
if (!uid_eq(cred->fsuid, file->f_inode->i_uid) &&
!capable(CAP_FOWNER))
return false;

return true;
}

// 可执行映射权限检查
static bool may_map_executable(struct cred *cred)
{
// 检查是否允许映射可执行文件
if (cred->noexec)
return false;

// 检查安全策略
return security_mmap_executable(cred) == 0;
}

9.2 地址空间隔离保护

  地址空间隔离的安全保护:

// 地址空间隔离验证
int validate_address_space_isolation(struct mm_struct *mm, unsigned long addr,
size_t len, unsigned long flags)
{
// 检查地址范围是否跨越安全边界
if (crosses_address_space_boundary(addr, len)) {
return EFAULT;
}

// 检查是否与现有映射冲突
if (conflicts_with_existing_mappings(mm, addr, len)) {
return EEXIST;
}

// 检查是否为受保护的地址范围
if (is_protected_address_range(addr, len)) {
// 需要特权访问
if (!capable(CAP_SYS_ADMIN) && !(flags & MAP_FIXED))
return EACCES;
}

// 验证地址空间布局随机化
if (!validate_aslr_compliance(mm, addr, flags)) {
return EACCES;
}

return 0;
}

// 地址空间边界检查
static bool crosses_address_space_boundary(unsigned long addr, size_t len)
{
unsigned long end = addr + len;

// 检查是否跨越用户/内核边界
if ((addr < TASK_SIZE && end > TASK_SIZE) ||
(addr < VMALLOC_START && end > VMALLOC_START)) {
return true;
}

// 检查是否跨越模块区域
if ((addr < MODULES_VADDR && end > MODULES_VADDR)) {
return true;
}

return false;
}

// 现有映射冲突检查
static bool conflicts_with_existing_mappings(struct mm_struct *mm,
unsigned long addr, size_t len)
{
struct vm_area_struct *vma;
unsigned long end = addr + len;

// 查找可能冲突的VMA
vma = find_vma(mm, addr);
while (vma && vma->vm_start < end) {
if (!(vma->vm_flags & VM_GAP) &&
overlaps_with_vma(vma, addr, end)) {
return true;
}
vma = vma->vm_next;
}

return false;
}

// ASLR合规性验证
static bool validate_aslr_compliance(struct mm_struct *mm, unsigned long addr,
unsigned long flags)
{
// 对于固定映射,ASLR不适用
if (flags & MAP_FIXED) {
return true;
}

// 检查地址是否符合ASLR随机化要求
if (mm->aslr_enabled) {
unsigned long expected_base = get_randomized_base(mm);
if (addr < expected_base || addr > expected_base + ASLR_RANGE) {
return false;
}
}

return true;
}

10. 扩展性分析

10.1 多架构支持

  跨架构的mmap扩展:

// 架构特定的mmap操作接口
struct arch_mmap_ops {
const char *arch_name;

// 地址分配
unsigned long (*get_unmapped_area)(struct file *, unsigned long,
unsigned long, unsigned long, unsigned long);

// 页表操作
int (*remap_pfn_range)(struct vm_area_struct *, unsigned long,
unsigned long, unsigned long, pgprot_t);

// 权限处理
unsigned long (*calc_vm_prot_bits)(unsigned long, unsigned long);
unsigned long (*calc_vm_flag_bits)(unsigned long);
};

// ARM64 mmap操作实现
static const struct arch_mmap_ops arm64_mmap_ops = {
.arch_name = "arm64",
.get_unmapped_area = arm64_get_unmapped_area,
.remap_pfn_range = arm64_remap_pfn_range,
.calc_vm_prot_bits = arm64_calc_vm_prot_bits,
.calc_vm_flag_bits = arm64_calc_vm_flag_bits,
};

// 运行时架构选择
static const struct arch_mmap_ops *select_arch_mmap_ops(void)
{
#ifdef CONFIG_ARM64
return &arm64_mmap_ops;
#else
return NULL;
#endif
}

10.2 功能扩展

  mmap功能扩展能力:

// 高级mmap功能扩展
struct advanced_mmap_features {
bool support_huge_pages; // 支持大页映射
bool support_transparent_huge; // 支持透明大页
bool support_memory_dedup; // 支持内存去重
bool support_userfaultfd; // 支持用户页面错误处理
bool support_mremap; // 支持映射重定位
bool support_madvise; // 支持内存建议
};

// mmap扩展API
struct extended_mmap_api {
// 大页映射
int (*mmap_huge)(unsigned long addr, size_t len, int prot, int flags,
int fd, off_t offset, int hugepage_size);

// 透明大页
int (*enable_thp)(struct mm_struct *mm);
int (*disable_thp)(struct mm_struct *mm);

// 内存去重
int (*enable_ksm)(struct mm_struct *mm, unsigned long start, unsigned long end);
int (*disable_ksm)(struct mm_struct *mm, unsigned long start, unsigned long end);

// 用户页面错误
int (*setup_userfaultfd)(struct vm_area_struct *vma, unsigned long flags);
int (*handle_userfault)(struct userfaultfd_ctx *ctx, unsigned long addr);

// 映射重定位
unsigned long (*mremap)(unsigned long old_addr, size_t old_len,
size_t new_len, int flags, unsigned long new_addr);

// 内存建议
int (*madvise)(unsigned long start, size_t len, int advice);
int (*process_madvise)(int pidfd, unsigned long start, size_t len, int advice);
};

11. 调试和维护

11.1 mmap调试支持

  mmap调试支持:

// mmap调试宏
#define MMAP_DEBUG(fmt, ...) \\
pr_debug("MMAP: " fmt, ##__VA_ARGS__)

#define MMAP_DEBUG_MAP(addr, len, prot, flags) \\
MMAP_DEBUG("mapping %lx-%lx prot=%x flags=%x\\n", addr, addr + len, prot, flags)

#define MMAP_DEBUG_VMA(vma) \\
MMAP_DEBUG("VMA %p [%lx-%lx] flags=%lx\\n", vma, vma->vm_start, vma->vm_end, vma->vm_flags)

// 详细调试模式
#ifdef CONFIG_MMAP_DEBUG
static void mmap_debug_mapping(struct vm_area_struct *vma, unsigned long addr,
unsigned long len, unsigned long prot, unsigned long flags)
{
MMAP_DEBUG("=== MMAP DEBUG ===");
MMAP_DEBUG("Address: %lx", addr);
MMAP_DEBUG("Length: %lx", len);
MMAP_DEBUG("Protection: %x", prot);
MMAP_DEBUG("Flags: %x", flags);

if (vma) {
MMAP_DEBUG("VMA created: %p", vma);
MMAP_DEBUG("VMA range: %lx-%lx", vma->vm_start, vma->vm_end);
MMAP_DEBUG("VMA flags: %lx", vma->vm_flags);
MMAP_DEBUG("VMA file: %p", vma->vm_file);
} else {
MMAP_DEBUG("Failed to create VMA");
}

MMAP_DEBUG("=== END MMAP DEBUG ===");
}
#endif

11.2 错误检测和恢复

  mmap错误处理:

// mmap错误检测
static int detect_mmap_errors(struct vm_area_struct *vma, unsigned long addr,
unsigned long len, int result)
{
// 检查映射结果
if (IS_ERR_VALUE(result)) {
MMAP_DEBUG("mmap failed: %d\\n", result);
return result;
}

// 验证VMA状态
if (!vma || vma->vm_start != addr || vma->vm_end != addr + len) {
MMAP_DEBUG("VMA validation failed\\n");
return EFAULT;
}

// 检查页表一致性
if (!validate_page_tables(vma)) {
MMAP_DEBUG("Page table validation failed\\n");
return EFAULT;
}

return 0;
}

// 错误恢复机制
static int recover_mmap_error(struct mm_struct *mm, unsigned long addr,
unsigned long len, int error)
{
MMAP_DEBUG("Attempting mmap error recovery: %d\\n", error);

switch (error) {
case ENOMEM:
// 内存不足:尝试释放缓存
return try_reclaim_memory(mm);

case EEXIST:
// 地址冲突:尝试重新分配地址
return try_relocate_mapping(mm, addr, len);

default:
MMAP_DEBUG("Unrecoverable mmap error\\n");
return error;
}
}

// 内存回收尝试
static int try_reclaim_memory(struct mm_struct *mm)
{
// 尝试回收页面缓存
if (shrink_page_cache(mm)) {
MMAP_DEBUG("Page cache reclaimed successfully\\n");
return 0;
}

// 尝试回收slab缓存
if (shrink_slab_cache()) {
MMAP_DEBUG("Slab cache reclaimed successfully\\n");
return 0;
}

return ENOMEM;
}

12. 总结

  ARM64 mm mmap子模块作为ARM64内存管理子系统中内存映射管理的核心组件,通过完整的地址空间管理、虚拟内存映射建立和权限控制机制,为ARM64平台提供了高效可靠的内存访问接口。该模块实现了匿名映射、文件映射、共享映射等多种映射类型,支持大页映射和透明大页等高级特性,在保证内存安全性的同时实现了接近硬件极限的映射性能。源码分析显示,模块采用了策略模式、工厂模式和观察者模式等多种设计模式,为内存映射管理提供了灵活高效的实现框架。

赞(0)
未经允许不得转载:网硕互联帮助中心 » Linux6.19-ARM64 mm mmap子模块深入分析
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!