[OS] sys_mmap() 函数+
流程图分析
1. 调用 sys_mmap()
- 步骤:当用户程序调用
mmap()
时,操作系统会进入sys_mmap()
函数。 - 作用:这是整个
mmap()
操作的入口。系统调用的实现从这里开始。
2. 提取参数(Fetch Argument)
- 步骤:从用户传递的系统调用中提取参数,例如映射的地址、长度、权限等。
- 作用:确保
mmap()
调用收到的参数正确无误,并且提取用户传递的所有必要信息。 - 错误处理:如果参数无效(例如,值无效或权限冲突),则返回错误
-1
,表示mmap()
失败。
3. 查找空闲的 VMA(Find a Free VMA)
- 步骤:在当前进程的 VMA 列表中查找一个可用的 VMA 槽位,来存储新的映射信息。
- 作用:每个 VMA 代表一个虚拟内存区域,系统通过这个步骤为新的映射区域找到一个合适的位置。
- 错误处理:如果没有可用的 VMA 槽位,则
panic("syscall mmap")
,表示系统找不到可用的映射区域。这种情况通常不会出现,除非进程的 VMA 数量达到上限。
4. 将信息记录到 VMA 结构中(Record Infos to VMA Structs)
- 步骤:将用户传递的参数(如起始地址、长度、权限等)记录到找到的 VMA 结构体中。
- 作用:将映射的相关信息存储在 VMA 中,便于操作系统后续管理和维护这个映射区域。
- 备注:这是
sys_mmap()
的核心步骤,确保进程中的 VMA 列表保存了每个映射的详细信息。
5. 增加文件的引用计数(filedup)
- 步骤:调用
filedup()
函数,增加文件的引用计数。 - 作用:表示这个文件有新的映射,确保文件在映射存在期间不会被删除或关闭。
- 备注:这一步是为了保证文件的一致性和安全性。引用计数的增加确保文件资源在映射期间被正确管理。
6. 返回虚拟地址(return virtual address)
- 步骤:
sys_mmap()
返回映射区域的起始虚拟地址给调用的用户程序。 - 作用:让用户程序知道映射区域的位置,以便可以直接访问映射的数据。
- 备注:这是
mmap()
调用的结果,用户程序可以通过返回的虚拟地址来访问文件内容。
关键步骤总结
- 参数检查:确保用户传递的参数合法,防止错误的映射请求。
- VMA 分配:从进程的 VMA 列表中找到一个空闲的槽位,记录映射信息。
- 文件引用管理:通过增加文件的引用计数,确保文件在映射期间不会被其他进程关闭。
- 返回映射地址:返回给用户一个虚拟地址,表示映射成功,方便用户直接访问映射的内存。
通俗解释
可以将这个流程想象成系统为用户程序分配一块“内存空间”的过程:
- 检查请求是否合理:先检查用户的请求是否符合要求(例如,要的内存大小、权限等)。
- 找到空位:在进程的 VMA 列表中找到一个空闲的位置,类似找到一张空桌子。
- 记录信息:把请求的内容记在这个位置上,确保以后系统知道这是用户申请的映射区域。
- 确保资源不被误用:增加文件的引用计数,确保这个文件不会在映射期间被其他操作关闭或修改。
- 返回地址:最后,把这块分配的空间地址返回给用户,方便用户直接使用。
实现的关键点
在实现 sys_mmap()
时,您需要关注以下几点:
- 参数验证:确保所有传入参数合法,包括地址、权限和大小等。
- VMA 分配逻辑:遍历 VMA 数组,找到一个空闲的 VMA,如果没有找到,返回错误。
- 记录映射信息:根据参数设置 VMA 结构体的各字段。
- 文件引用计数管理:调用
filedup()
增加文件的引用计数,保证文件在映射期间的有效性。 - 返回虚拟地址:最终返回映射区域的地址,供用户直接访问。
从图片中可以看出,在 sys_mmap
的实现过程中,需要从系统调用中获取传递的参数,而这些参数是通过 trapframe 来存储的。以下是对这个过程的详细分析。
关键问题
问题:如何获取 sys_mmap
的参数?
在 sys_mmap
的实现中,我们并没有直接从函数的参数列表中看到用户传递的参数(例如,地址、长度、权限等)。那么,如何从系统调用中获取这些参数呢?
答案:利用 trapframe
在 xv6 操作系统中,系统调用的参数是通过 trapframe 结构体来存储的。trapframe 是每个进程在发生系统调用或中断时,存储 CPU 寄存器状态的结构体。参数会被传递到特定的寄存器中,然后被 trapframe
捕获和存储。
在 proc
结构体中,每个进程都有一个 trapframe,其中包含了这些系统调用参数的寄存器值。因此,我们可以通过访问 trapframe
中的特定字段(例如 a0
到 a5
)来获取这些参数。
arghraw()
函数的作用
代码右侧显示了一个函数 argraw(int n)
,它用于从当前进程的 trapframe
中获取参数:
static uint64 arghraw(int n) {struct proc *p = myproc();switch (n) {case 0: return p->trapframe->a0;case 1: return p->trapframe->a1;case 2: return p->trapframe->a2;case 3: return p->trapframe->a3;case 4: return p->trapframe->a4;case 5: return p->trapframe->a5;}panic("arghraw");return -1;
}
作用分析
- 参数索引:
arghraw()
函数接受一个整数n
,代表参数的索引。系统调用中最多可以传递 6 个参数(a0
到a5
)。 - 获取参数值:函数通过
switch
语句,根据参数的索引值n
,返回trapframe
中对应的寄存器值。这些寄存器保存了系统调用时传入的参数值。 - 错误处理:如果
n
超出范围,函数会触发panic
,表示参数获取失败。
具体步骤
在实现 sys_mmap
时,可以通过调用 arghraw(n)
来获取每个参数。例如:
uint64 addr = arghraw(0); // 获取地址参数
size_t length = arghraw(1); // 获取长度参数
int prot = arghraw(2); // 获取权限参数
int flags = arghraw(3); // 获取标志参数
int fd = arghraw(4); // 获取文件描述符参数
off_t offset = arghraw(5); // 获取偏移量参数
总结
- trapframe 记录了系统调用的参数值,参数存储在寄存器中。
- 通过
arghraw()
函数,可以从trapframe
中按索引顺序提取参数,以便在sys_mmap
中使用。 arghraw()
的switch
语句确保了可以灵活获取从a0
到a5
的任意一个参数值。
通俗解释
可以把 trapframe 想象成进程的“快照记录本”。当系统调用发生时,操作系统会将参数值保存在 “记录本” 中的特定位置(即寄存器 a0
到 a5
)。arghraw()
就像一个“翻页函数”,根据参数的顺序翻到对应的寄存器位置,读取参数值,然后返回给系统调用。
1. 什么是 trapframe
?
trapframe 是一个结构体,用于保存进程在发生系统调用、中断或异常时的 CPU 寄存器状态。可以把它想象成操作系统在处理系统调用或中断时,记录当前进程状态的“备忘录”。
当程序发生系统调用或中断时,CPU 的寄存器会被用来传递参数和执行控制流切换。为了在系统调用处理完后能够让程序继续执行,操作系统会在进入内核之前把寄存器状态(包括系统调用的参数)保存到 trapframe 中。这样,在完成系统调用后,操作系统可以恢复寄存器状态,让程序从中断前的状态继续运行。
2. trapframe
从哪里来?
在 xv6 等操作系统中,每个进程都有一个独立的 trapframe
,它是进程控制块(即 proc
结构体)的一部分。proc
结构体中的 trapframe
指针指向了保存当前进程状态的 trapframe
。
- 创建进程时:操作系统会为每个进程分配一个
trapframe
。 - 系统调用或中断发生时:操作系统会将当前 CPU 寄存器的值保存到
trapframe
中,以备稍后恢复。 - 系统调用处理完成后:操作系统将
trapframe
中保存的寄存器状态恢复到 CPU 中,继续执行进程。
3. trapframe
的作用是什么?
trapframe
的主要作用是在进程进入内核态时保存其状态。具体作用如下:
- 保存寄存器状态:在进入系统调用或中断时,CPU 寄存器的值会被存储到
trapframe
中,包括系统调用传递的参数、程序计数器等。 - 恢复现场:在系统调用完成后,操作系统会将
trapframe
中的状态恢复到 CPU 寄存器,让进程继续执行。
4. trapframe
和 sys_mmap
的关系
在 sys_mmap
中,我们需要获取用户传递的参数,而这些参数在系统调用发生时被保存在 trapframe
的寄存器字段中。具体来说:
- 当用户调用
mmap()
时,传递的参数会存储在寄存器a0
到a5
中(因为 RISC-V 架构的系统调用参数通过这几个寄存器传递)。 - 操作系统会将这些寄存器值存储在
trapframe
的相应字段中。 sys_mmap
可以通过proc
结构体中的trapframe
指针,读取寄存器中的参数值,完成系统调用所需的操作。
5. argraw
函数如何使用 trapframe
在 sys_mmap
中,我们使用 argraw
函数从 trapframe
中提取系统调用的参数值。
static uint64 arghraw(int n) {struct proc *p = myproc(); // 获取当前进程的 proc 结构体switch (n) {case 0: return p->trapframe->a0;case 1: return p->trapframe->a1;case 2: return p->trapframe->a2;case 3: return p->trapframe->a3;case 4: return p->trapframe->a4;case 5: return p->trapframe->a5;}panic("arghraw");return -1;
}
- 步骤:
arghraw
函数通过myproc()
获取当前进程的proc
结构体。proc
结构体中有一个指向trapframe
的指针,通过它可以访问系统调用参数。switch
语句根据参数的顺序n
,返回trapframe
中相应的寄存器值(即参数值)。
6. 通俗解释
可以将 trapframe
想象成一个“暂停存储器”。当程序进入内核,发生系统调用时,操作系统会将程序的寄存器状态保存到 trapframe
,相当于“暂停”了程序。等系统调用执行完毕,操作系统会使用 trapframe
中的信息,将程序恢复到调用前的状态,相当于“继续”运行程序。
- 为什么
trapframe
重要? 因为系统调用是程序和操作系统交互的桥梁,而trapframe
确保了程序在交互过程中不会丢失任何状态。 sys_mmap
和trapframe
的关系:sys_mmap
是一种系统调用,它的参数通过trapframe
保存,sys_mmap
可以通过trapframe
获取这些参数。
总结
trapframe
是一个寄存器状态的备份,每次系统调用都会更新它。trapframe
是proc
结构体的一部分,可以通过proc
获取它。- 在
sys_mmap
中,通过trapframe
获取系统调用参数,确保正确执行mmap
操作。
相关文章:

[OS] sys_mmap() 函数+
流程图分析 1. 调用 sys_mmap() 步骤:当用户程序调用 mmap() 时,操作系统会进入 sys_mmap() 函数。作用:这是整个 mmap() 操作的入口。系统调用的实现从这里开始。 2. 提取参数(Fetch Argument) 步骤:从…...
轧钢机辊道多电动机传动控制系统
轧钢机辊道多电动机传动控制系统是一种复杂的工业自动化系统,主要用于控制轧钢车间中多个电动机驱动的辊道,以实现轧件的高效、稳定输送和加工。以下是对该系统的详细介绍: 系统组成 轧线辊道TDC控制器:作为系统的核心控制单元&a…...

使用 Nginx 部署 Python 项目
今天的目标是完成一个 Python Web 项目的线上部署,我们使用最新的 Django 项目搭建一个简易的 Web 工程,然后基于 Nginx 服务部署该 Python Web 项目。 1. 前期准备 1.1 安装虚拟环境pyenv 使用虚拟环境逐渐成了 python 项目开发中的一种主流方式。py…...
[笔记] SQL 优化
一. 数据库设计优化 1. 选择合适的字段类型 设计表时,尽量选择存储空间小的字段类型: 整型字段:从TINYINT、SMALLINT、INT到BIGINT。小数类型:对于金额等需精确计算的数值使用DECIMAL,避免使用FLOAT和DOUBLE。字符串…...

【InfluxDB】InfluxDB 2.x基础概念及原理
InfluxDB简介 什么是时序数据库 时序数据库,全称时间序列数据库(Time Series Database,TSDB),用于存储大量基于时间的数据。时序数据库支持时序数据的快速写入、持久化,多维度查询、聚合等操作࿰…...

.net Core 使用Panda.DynamicWebApi动态构造路由
我们以前是通过创建controller来创建API,通过controller来显示的生成路由,这里我们讲解下如何不通过controller,构造API路由 安装 Panda.DynamicWebApi 1.2.2 1.2.2 Swashbuckle.AspNetCore 6.2.3 6.2.3添加ServiceAction…...
Spring框架和Spring Boot框架都使用注解来简化配置和提高开发效率,但它们之间存在一些区别
Spring框架和Spring Boot框架都使用注解来简化配置和提高开发效率,但它们之间存在一些区别: Spring框架注解: Autowired:自动导入对象到类中,被注入的类需要被Spring容器管理。Component、Repository、Service、Contro…...

从数据提取到管理:TextIn平台的全面解析与产品体验
一、引言 在现代信息时代,文档解析和管理已经成为企业和开发者不可或缺的工具。TextIn是合合信息旗下的一款智能文档处理平台,为开发者和企业提供高效、精准的文档解析工具,帮助用户轻松应对各种复杂的文档处理需求。本文将深入探讨TextIn的…...
2024 Rust现代实用教程 Error错误处理
文章目录 一、错误处理之:Result、Option以及panic!宏1.Result2.Option3.panic! 二、错误处理之:unwrap()与?1.unwrap()2.?运算符 三、自定义一个Error类型参考 一、错误处理之:Result、Option以及panic!宏 Rust中的错误可以分为…...
android 逆向破解360加固(MT管理器反编译)
1.需要准备的环境MT管理器 2.一台root手机 3,需要给app脱壳https://nop.gs/在这里脱壳 4.将脱壳的文件解压之后解压 5.用MT管理器打开需要反编译破解的app 6.然后把脱壳的classes.dex添加到破解的app里面删除原来的classes.dex 7.删除360加固的so,so在assets文件里面删除libjia…...
使用 SSH 蜜罐提升安全性和记录攻击活动
文章目录 使用 SSH 蜜罐提升安全性和记录攻击活动前言整体逻辑讲解安全最佳实践蜜罐的类型与选择数据分析与响应进一步学习资源修改 SSH 服务端口部署 FakeSSHFakeSSH 简介部署步骤记录攻击 部署 SSHSameSSHSame 简介部署步骤观察攻击行为 总结 使用 SSH 蜜罐提升安全性和记录攻…...

无人机拦截捕获/直接摧毁算法详解!
一、无人机拦截捕获算法 网捕技术 原理:抛撒特殊设计的网具,捕获并固定无人机。 特点: 适用于小型无人机。 对无人机的损害较小,基本不影响其后续使用。 捕获成功率较高,且成本相对较低。 应用实例:…...

后端eclipse——文字样式:UEditor富文本编辑器引入
目录 1.富文本编辑器的优点 2.文件的准备 3.文件的导入 导入到项目: 导入到html文件: 编辑 4.富文本编辑器的使用 1.富文本编辑器的优点 我们从前端写入数据库时,文字的样式具有局限性,不能存在换行,更改字体…...
thinkphp6 redis 哈希存储方式以及操作函数(笔记)
逻辑:如果redis里没有指定表数据就进行存储再输出,如果有就直接输出,代码优化后几万条数据从数据库入redis也是三四秒的时间,数据以json方式存储:key用于数据ID 跟数据库数据ID同步,value用于存储整个字段包…...

「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
本篇将带你实现一个滑动选择器应用,用户可以通过滑动条选择不同的数值,并实时查看选定的值和提示。这是一个学习如何使用 Slider 组件、状态管理和动态文本更新的良好实践。 关键词 UI互动应用Slider 组件状态管理动态数值更新用户交互 一、功能说明 在…...

【嵌入式】STM32中的SPI通信
SPI是由摩托罗拉公司开发的一种通用数据总线,其中由四根通信线,支持总线挂载多设备(一主多从),是一种同步全双工的协议。主要是实现主控芯片和外挂芯片之间的交流。这样可以使得STM32可以访问并控制各种外部芯片。本文…...
后端:Spring、Spring Boot-配置、定义bean
文章目录 1. 什么是Bean,如何配置2. 如何配置bean2.1 使用注解Bean2.2 使用注解Import 1. 什么是Bean,如何配置 被spring容器所管理的对象被称为bean,管理方式可以有纯xml文件方式、注解方式进行管理(比如注解Component)。 在Spring Boot中&…...
【Git】Git 远程仓库命令详解
目录 引言1. Git Fetch、Git Pull 和 Git Push 简介1.1 概念总结1.2 图示概念 2. 分支的概念2.1 分支定义2.2 分支的特点2.3 分支示例2.4 基本操作命令2.5 分支的使用场景 3. Git Fetch 用法3.1 基本命令3.2 获取特定分支3.3 查看更新内容3.4 使用示例3.5 适用场景 4. Git Pull…...

html简易流程图
效果图 使用htmlcssjs,无图片,没用Canvas demo: <!DOCTYPE html> <html> <head><link href"draw.css" rel"stylesheet" /><script src"draw.js" type"text/javascript"></…...

Java 入门
目录 Java简介 Java JDK开发环境配置 第一个Java程序 Java标识符与关键字 Java注释 Java常量 Java变量的定义和使用 Java简介 Java简介: Java是由Sun Microsystems公司于1995年推出的一门面向对象的高级程序设计语言,可以运行于多个平台,其…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...