OpenHarmony之系统调用
OpenHarmony之系统调用
背景
对于运行L0系统的硬件一般是mcu,资源有限,L0系统没有区分内核态和用户态,所有的代码都在内核态运行,所以不需要系统调用
L2系统用的是Linux内核,所以系统调用跟Linux Kernel的是一样的。可以参见我之前的博文Linux之系统调用
所以我们主要来看看L1系统中系统调用机制的是怎么实现的。
后面的分析基于如下版本:
- OpenHarmony v3.3.2
- musl v1.2.0
L1系统调用
对于运行L1系统的硬件一般集成了MMU,而且CPU有特权级别状态(状态寄存器的某些位),可以实现进程之间的隔离、内核态和用户态的隔离。系统调用就是在有内核态和用户态隔离的操作系统上,用户态进程访问内核态资源的一种方式
用户态c库
通常我们的应用不会直接调用系统调用,而是通过c库的库函数来间接调用。
OpenHarmony上层使用的C库是musl libc
, c库的一些函数接口调到最下面就是系统调用接口了。
通过third_party/musl/src/internal/syscall.h
文件中,各种宏的展开,最终都会变成类似与__syscall3
等这样的函数(后面可能跟着不同的数字,代表传递参数的个数),而 musl libc 对于这些函数在不同硬件架构上有着不同的实现,这里以arm为例,
代码路径:third_party/musl/arch/arm/syscall_arch.h
主要代码:
#define __asm_syscall(...) do { \
__asm__ __volatile__ ( "svc 0" \
: "=r"(r0) : __VA_ARGS__ : "memory"); \
return r0; \
} while (0)
#endif
这里调用了SVC
指令触发一个“特权调用”异常,并传递一些参数,这样会触发内核去处理该中断。
内核态中断处理
SVC中断后,内核就会去处理该中断。
中断异常处理的入口是在汇编代码:kernel/liteos_a/arch/arm/arm/src/los_hw_exc.S
SVC异常处理函数入口:_osExceptSwiHdl
,
最终会调用到所有系统调用的统一入口, 这里就是C代码实现了:OsArmA32SyscallHandle
(kernel/liteos_a/syscall/los_syscall.c
)
这里会根据系统调用号来查找对应的系统调用处理函数(syscall_lookup.h
中定义了对应的处理函数),然后通过这些处理函数和传递过来的参数,由此完成真正系统调用的过程,这里就不再一一分析了。
总结
本篇只是记录了一下OpenHarmony的L1系统系统调用实现的大致流程,梳理下整个脉络。
整个流程大致如下:
应用程序
--> c库函数 (musl libc)
--> 系统调用
--> 触发`SVC`中断
--> 内核态SVC异常处理函数
--> 系统调用具体实现及返回
这里也不列举例子了,具体的可以自己去撸下代码。