v37.06 鸿蒙内核源码分析(系统调用) | 开发者永远的口头禅 原创
子曰:“苗而不秀者有矣夫!秀而不实者有矣夫!” 《论语》:子罕篇
百篇博客系列篇.本篇为:
v37.xx 鸿蒙内核源码分析(系统调用篇) | 开发者永远的口头禅
任务管理相关篇为:
- v03.06 鸿蒙内核源码分析(时钟任务) | 触发调度谁的贡献最大
- v04.03 鸿蒙内核源码分析(任务调度) | 任务是内核调度的单元
- v05.05 鸿蒙内核源码分析(任务管理) | 任务池是如何管理的
- v06.03 鸿蒙内核源码分析(调度队列) | 内核有多少个调度队列
- v07.08 鸿蒙内核源码分析(调度机制) | 任务是如何被调度执行的
- v21.07 鸿蒙内核源码分析(线程概念) | 是谁在不断的折腾CPU
- v25.05 鸿蒙内核源码分析(并发并行) | 听过无数遍的两个概念
- v32.03 鸿蒙内核源码分析(CPU) | 整个内核就是一个死循环
- v37.06 鸿蒙内核源码分析(系统调用) | 开发者永远的口头禅
- v41.03 鸿蒙内核源码分析(任务切换) | 看汇编如何切换任务
本篇说清楚系统调用
读本篇之前建议先读鸿蒙内核源码分析(总目录)工作模式篇.
本篇通过一张图和七段代码详细说明系统调用的整个过程,代码一捅到底,直到汇编层再也捅不下去.
先看图,这里的模式可以理解为空间,因为模式不同运行的栈空间就不一样.
过程解读
- 在应用层
main
中使用系统调用mq_open
(posix标准接口) mq_open
被封装在库中,这里直接看库里的代码.mq_open
中调用syscall
,将参数传给寄出器R7,R0~R6
SVC 0
完成用户模式到内核模式(SVC)的切换_osExceptSwiHdl
运行在svc模式下.- PC寄存器直接指向
_osExceptSwiHdl
处取指令. _osExceptSwiHdl
是汇编代码,先保存用户模式现场(R0~R12寄存器),并调用OsArmA32SyscallHandle
完成系统调用OsArmA32SyscallHandle
中通过系统调用号(保存在R7寄存器)查询对应的注册函数SYS_mq_open
SYS_mq_open
是本次系统调用的实现函数,完成后return回到OsArmA32SyscallHandle
OsArmA32SyscallHandle
再return回到_osExceptSwiHdl
_osExceptSwiHdl
恢复用户模式现场(R0~R12寄存器)- 从内核模式(SVC)切回到用户模式,PC寄存器也切回用户现场.
- 由此完成整个系统调用全过程
七段追踪代码,逐个分析
1.应用程序 main
2. mq_open 发起系统调用
解读
SYS_mq_open
是真正的系统调用函数,对应一个系统调用号__NR_mq_open
,通过宏SYSCALL_HAND_DE
F将SysMqOpen
注册到g_syscallHandle
中.
g_syscallNArgs
为注册函数的参数个数,也会一块记录下来.- 四个参数为 SYS_mq_open的四个参数,后续将保存在R0~R3寄存器中
3. syscall
解读
- 可变参数实现所有系统调用的参数的管理,可以看出,在鸿蒙内核中系统调用的参数最多不能大于6个
- R7寄存器保存了系统调用号,R0~R5保存具体每个参数
- 可变参数的具体实现后续有其余篇幅详细介绍,敬请关注.
4. svc 0
看不太懂的没关系,这里我们只需要记住:系统调用号存放在r7寄存器,参数存放在r0,r1,r2寄存器中,返回值最终会存放在寄存器r0中
解读
svc
全称是 SuperVisor Call,完成工作模式的切换.不管之前是7个模式中的哪个模式,统一都切到SVC
管理模式.但你也许会好奇,ARM软中断不是用SWI
吗,这里怎么变成了SVC
了,请看下面一段话,是从ARM官网翻译的:SVC
超级用户调用。
语法
SVC{cond} #immed
其中:
cond
是一个可选的条件代码(请参阅条件执行)。
immed
是一个表达式,其取值为以下范围内的一个整数:
在 ARM 指令中为 0 到 224–1(24 位值)
在 16 位 Thumb 指令中为 0-255(8 位值)。
用法
SVC 指令会引发一个异常。 这意味着处理器模式会更改为超级用户模式,CPSR 会保存到超级用户模式 SPSR,并且执行会跳转到 SVC 向量(请参阅《开发指南》中的第 6 章 处理处理器异常)。
处理器会忽略 immed。 但异常处理程序会获取它,借以确定所请求的服务。
Note
作为 ARM 汇编语言开发成果的一部分,SWI 指令已重命名为 SVC。 在此版本的 RVCT 中,SWI 指令反汇编为 SVC,并提供注释以指明这是以前的 SWI。
条件标记
此指令不更改标记。
体系结构
此 ARM 指令可用于所有版本的 ARM 体系结构。- 而软中断对应的处理函数为
_osExceptSwiHdl
,即PC寄存器将跳到_osExceptSwiHdl
执行
5. _osExceptSwiHdl
解读
- 运行到此处,已经切到SVC的栈运行,所以先保存上一个模式的现场
- 获取中断模式,软中断的来源可不一定是用户模式,完全有可能是SVC本身,比如系统调用中又发生系统调用.就变成了从SVC模式切到SVC的模式
MOV R0, SP
;sp将作为参数传递给OsArmA32SyscallHandle
- 调用
OsArmA32SyscallHandle
这是所有系统调用的统一入口 - 注意看
OsArmA32SyscallHandle
的参数UINT32 *regs
6. OsArmA32SyscallHandle
解读
- 参数是
regs
对应的就是R0~Rn - R7保存的是系统调用号,R0~R3保存的是
SysMqOpen
的四个参数 g_syscallHandle[cmd]
就能查询到SYSCALL_HAND_DEF(__NR_mq_open, SysMqOpen, mqd_t, ARG_NUM_4)
注册时对应的SysMqOpen
函数*(SyscallFun5)handle
此时就是SysMqOpen
- 注意看 SysMqOpen 的参数是最开始的
main
函数中的
mqdes = mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, &attr);
由此完成了真正系统调用的过程
7. SysMqOpen
解读
- 此处的
mq_open
和main函数的mq_open
其实是两个函数体实现.一个是给应用层的调用,一个是内核层使用,只是名字一样而已. SysMqOpen
是返回到OsArmA32SyscallHandle
regs[REG_R0] = ret;
OsArmA32SyscallHandle
再返回到_osExceptSwiHdl
_osExceptSwiHdl
后面的代码是用于恢复用户模式现场和SPSR
,PC
等寄存器.
以上为鸿蒙系统调用的整个过程.
关于寄存器(R0~R15)在每种模式下的使用方式,后续将由其他篇详细说明,敬请关注.
百万汉字注解.精读内核源码
百篇博客分析.深挖内核地基
给鸿蒙内核源码加注释过程中,整理出以下文章。内容立足源码,常以生活场景打比方尽可能多的将内核知识点置入某种场景,具有画面感,容易理解记忆。说别人能听得懂的话很重要! 百篇博客绝不是百度教条式的在说一堆诘屈聱牙的概念,那没什么意思。更希望让内核变得栩栩如生,倍感亲切.确实有难度,自不量力,但已经出发,回头已是不可能的了。 😛
与代码有bug需不断debug一样,文章和注解内容会存在不少错漏之处,请多包涵,但会反复修正,持续更新,.xx
代表修改的次数,精雕细琢,言简意赅,力求打造精品内容。
基础工具>> 双向链表 | 位图管理 | 用栈方式 | 定时器 | 原子操作 | 时间管理 |
加载运行>> ELF格式 | ELF解析 | 静态链接 | 重定位 | 进程映像 |
进程管理>> 进程管理 | 进程概念 | Fork | 特殊进程 | 进程回收 | 信号生产 | 信号消费 | Shell编辑 | Shell解析 |
编译构建>> 编译环境 | 编译过程 | 环境脚本 | 构建工具 | gn应用 | 忍者ninja |
进程通讯>> 自旋锁 | 互斥锁 | 进程通讯 | 信号量 | 事件控制 | 消息队列 |
内存管理>> 内存分配 | 内存管理 | 内存汇编 | 内存映射 | 内存规则 | 物理内存 |
前因后果>> 总目录 | 调度故事 | 内存主奴 | 源码注释 | 源码结构 | 静态站点 |
任务管理>> 时钟任务 | 任务调度 | 任务管理 | 调度队列 | 调度机制 | 线程概念 | 并发并行 | CPU | 系统调用 | 任务切换 |
文件系统>> 文件概念 | 文件系统 | 索引节点 | 挂载目录 | 根文件系统 | 字符设备 | VFS | 文件句柄 | 管道文件 |
硬件架构>> 汇编基础 | 汇编传参 | 工作模式 | 寄存器 | 异常接管 | 汇编汇总 | 中断切换 | 中断概念 | 中断管理 |
鸿蒙研究站 | 每天死磕一点点,原创不易,欢迎转载,但请注明出处。
感谢大佬分享。_osExceptSwiHdl这块代码和最新代码差别挺大的。
这是最新的:
文中的截图 PDF文档资料能给个链接吗?哪里可以下载 arm官网上没有找到位置
是的,官方对汇编部分做过一次更新, 博客和注解没有及时同步. 但意思差不多, 结合注释看也容易看明白.
晚点我整理出来,关注 weharmonyos.com 上的更新