[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年推出的一门面向对象的高级程序设计语言,可以运行于多个平台,其…...

JVM基本结构和垃圾回收机制
一、JVM基本结构 Java虚拟机(JVM, Java Virtual Machine)是Java程序执行的环境,其基本结构可以分为以下几个主要部分: 类加载器子系统(Class Loader Subsystem): 负责加载Java类文件到内存中。…...

CentOS 7 安装 ntp,自动校准系统时间
1、安装 ntp yum install ntp 安装好后,ntp 会自动注册成为服务,服务名称为 ntpd 2、查看当前 ntpd 服务的状态 systemctl status ntpd 3、启动 ntpd 服务、查看 ntpd 服务的状态 systemctl start ntpdsystemctl status ntpd 4、设置 ntpd 服务开机启…...

Spring Boot 配置文件启动加载顺序
前言 Spring Boot的启动加载顺序是一个涉及多个步骤和组件的过程。Spring Boot通过一系列默认设置简化了应用程序的配置,使得开发者能够快速地搭建和部署应用。为了实现这一目标,Spring Boot采用了一种分层和优先级机制来加载配置文件。 一、Spring Bo…...

webrtc agc2实现原理
WebRTC的AGC2(自适应增益控制器)是一种用于音频处理的算法,可以根据输入信号的强度自动调整增益,使输出信号的音量保持稳定。其详细原理如下: 噪声估计 首先,AGC2需要对输入信号中的噪声进行估计ÿ…...

2024.11.03 周报
一 实时超分音频同步问题: 处理方向: 按照胡学长的办法尝试: 前面处理视频, 将视频中音频提取出来, 将音频每隔 1-2 秒保存为一段 (这样将音频缓存在内存中) , 然后依次播放, 但是音频是44.1KHz采样率,每秒44100次的频率. 每次间隔中程序处理的极短时间…...

Oceanbase学习之一迁移mysql数据到oceanbase
一、数据库环境 #mysql环境 root192.168.150.162 20:28: [(none)]> select version(); ---------- | version() | ---------- | 8.0.26 | ---------- 1 row in set (0.00 sec) root192.168.150.162 20:28: [(none)]> show variables like ‘%char%’; ---…...

Milvus - GPU 索引类型及其应用场景
1. 背景概述 Milvus 是一款高效的矢量数据库管理系统,支持在高并发和高调用场景下加速相似度搜索。Milvus 的 GPU 支持由 NvidiaRAPIDS 团队提供,可以借助各种 GPU 索引类型来优化性能。本篇将重点解析 Milvus 支持的 GPU 索引类型、适用场景及各自的性…...

Webserver(2.8)守护进程
目录 守护进程案例 守护进程案例 每隔2s获取系统时间,将这个时间写入到磁盘文件中 #include<stdio.h> #include<sys/stat.h> #include<sys/types.h> #include<unistd.h> #include<fcntl.h> #include<sys/time.h> #include<…...

HarmonyOS :
HarmonyOS 移动应用开发 什么是HarmonyOS?: 官方解释:HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统。 鸿蒙操作系统在传统的单设备系统能力的基础上,提出了基于同一套系统能力、适配多种终端形态的分布式理念&#…...

C# EF 使用
WPF EF MySQL - - -版本.NET Framework4.7.2EntityFramework6.5.1MySql.Data.EntityFramework9.1.0 创建数据库 ccApp.config <connectionStrings><add name"MyDbContext" providerName"MySql.Data.MySqlClient" connectionString"server…...