文章目录
- 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(¤t->mm->mm_rb, addr, len, pgoff, flags);
if (!(flags & MAP_FIXED) && addr & ~PAGE_MASK)
return vm_unmapped_area_topdown(¤t->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平台提供了高效可靠的内存访问接口。该模块实现了匿名映射、文件映射、共享映射等多种映射类型,支持大页映射和透明大页等高级特性,在保证内存安全性的同时实现了接近硬件极限的映射性能。源码分析显示,模块采用了策略模式、工厂模式和观察者模式等多种设计模式,为内存映射管理提供了灵活高效的实现框架。
网硕互联帮助中心



评论前必须登录!
注册