1# 系统调用 2 3 4## 基本概念 5 6OpenHarmony LiteOS-A实现了用户态与内核态的区分隔离,用户态程序不能直接访问内核资源,而系统调用则为用户态程序提供了一种访问内核资源、与内核进行交互的通道。 7 8 9## 运行机制 10 11 如图1所示,用户程序通过调用System API(系统API,通常是系统提供的POSIX接口)进行内核资源访问与交互请求,POSIX接口内部会触发SVC/SWI异常,完成系统从用户态到内核态的切换,然后对接到内核的Syscall Handler(系统调用统一处理接口)进行参数解析,最终分发至具体的内核处理函数。 12 13 **图1** 系统调用示意图 14 15 ![zh-cn_image_0000001132856572](figures/zh-cn_image_0000001132856572.png) 16Syscall Handler的具体实现在kernel/liteos_a/syscall/los_syscall.c中OsArmA32SyscallHandle函数,在进入系统软中断异常时会调用此函数,并且按照kernel/liteos_a/syscall/syscall_lookup.h中的清单进行系统调用的入参解析,执行各系统调用最终对应的内核处理函数。 17 18> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** 19> - 系统调用提供基础的用户态程序与内核的交互功能,不建议开发者直接使用系统调用接口,推荐使用内核提供的对外POSIX接口,若需要新增系统调用接口,详见开发指导。 20> 21> - 内核向用户态提供的系统调用接口清单详见kernel/liteos_a/syscall/syscall_lookup.h,内核相应的系统调用对接函数清单详见kernel/liteos_a/syscall/los_syscall.h。 22 23 24## 开发指导 25 26 27### 开发流程 28 29新增系统调用的典型开发流程如下: 30 311. 在LibC库中确定并添加新增的系统调用号。 32 332. 在LibC库中新增用户态的函数接口声明及实现。 34 353. 在内核系统调用头文件中确定并添加新增的系统调用号及对应内核处理函数的声明。 36 374. 在内核中新增该系统调用对应的内核处理函数。 38 39 40### 编程实例 41 42**示例代码**: 43 441. 在LibC库syscall.h.in中新增系统调用号 45 如下所示,其中__NR_new_syscall_sample为新增系统调用号: 46 47 ``` 48 ... 49 /* 当前现有的系统调用清单 */ 50 /* OHOS customized syscalls, not compatible with ARM EABI */ 51 #define __NR_OHOS_BEGIN 500 52 #define __NR_pthread_set_detach (__NR_OHOS_BEGIN + 0) 53 #define __NR_pthread_join (__NR_OHOS_BEGIN + 1) 54 #define __NR_pthread_deatch (__NR_OHOS_BEGIN + 2) 55 #define __NR_create_user_thread (__NR_OHOS_BEGIN + 3) 56 #define __NR_processcreate (__NR_OHOS_BEGIN + 4) 57 #define __NR_processtart (__NR_OHOS_BEGIN + 5) 58 #define __NR_printf (__NR_OHOS_BEGIN + 6) 59 #define __NR_dumpmemory (__NR_OHOS_BEGIN + 13) 60 #define __NR_mkfifo (__NR_OHOS_BEGIN + 14) 61 #define __NR_mqclose (__NR_OHOS_BEGIN + 15) 62 #define __NR_realpath (__NR_OHOS_BEGIN + 16) 63 #define __NR_format (__NR_OHOS_BEGIN + 17) 64 #define __NR_shellexec (__NR_OHOS_BEGIN + 18) 65 #define __NR_ohoscapget (__NR_OHOS_BEGIN + 19) 66 #define __NR_ohoscapset (__NR_OHOS_BEGIN + 20) 67 68 #define __NR_new_syscall_sample (__NR_OHOS_BEGIN + 21) /* 新增的系统调用号 __NR_new_syscall_sample:521 */ 69 70 #define __NR_syscallend (__NR_OHOS_BEGIN + 22) 71 ... 72 ``` 73 742. 在LibC库中新增用户态接口的声明与实现 75 76 ``` 77 #include "stdio_impl.h" 78 #include "syscall.h" 79 ... 80 /* 新增系统调用用户态的接口实现 */ 81 void newSyscallSample(int num) 82 { 83 printf("user mode: num = %d\n", num); 84 __syscall(SYS_new_syscall_sample, num); 85 return; 86 } 87 ``` 88 893. 在内核系统调用头文件中新增系统调用号 90 如下所示,在third_party/musl/porting/liteos_a/kernel/include/bits/syscall.h文件中,__NR_new_syscall_sample为新增系统调用号。 91 92 93 ``` 94 ... 95 /* 当前现有的系统调用清单 */ 96 /* OHOS customized syscalls, not compatible with ARM EABI */ 97 #define __NR_OHOS_BEGIN 500 98 #define __NR_pthread_set_detach (__NR_OHOS_BEGIN + 0) 99 #define __NR_pthread_join (__NR_OHOS_BEGIN + 1) 100 #define __NR_pthread_deatch (__NR_OHOS_BEGIN + 2) 101 #define __NR_create_user_thread (__NR_OHOS_BEGIN + 3) 102 #define __NR_processcreate (__NR_OHOS_BEGIN + 4) 103 #define __NR_processtart (__NR_OHOS_BEGIN + 5) 104 #define __NR_printf (__NR_OHOS_BEGIN + 6) 105 #define __NR_dumpmemory (__NR_OHOS_BEGIN + 13) 106 #define __NR_mkfifo (__NR_OHOS_BEGIN + 14) 107 #define __NR_mqclose (__NR_OHOS_BEGIN + 15) 108 #define __NR_realpath (__NR_OHOS_BEGIN + 16) 109 #define __NR_format (__NR_OHOS_BEGIN + 17) 110 #define __NR_shellexec (__NR_OHOS_BEGIN + 18) 111 #define __NR_ohoscapget (__NR_OHOS_BEGIN + 19) 112 #define __NR_ohoscapset (__NR_OHOS_BEGIN + 20) 113 114 #define __NR_new_syscall_sample (__NR_OHOS_BEGIN + 21) /* 新增的系统调用号 __NR_new_syscall_sample:521 */ 115 116 #define __NR_syscallend (__NR_OHOS_BEGIN + 22) 117 ... 118 ``` 119 120 在kernel/liteos_a/syscall/syscall_lookup.h中,增加一行SYSCALL_HAND_DEF(__NR_new_syscall_sample, SysNewSyscallSample, void, ARG_NUM_1): 121 122 123 ``` 124 ... 125 /* 当前现有的系统调用清单 */ 126 SYSCALL_HAND_DEF(__NR_chown, SysChown, int, ARG_NUM_3) 127 SYSCALL_HAND_DEF(__NR_chown32, SysChown, int, ARG_NUM_3) 128 #ifdef LOSCFG_SECURITY_CAPABILITY 129 SYSCALL_HAND_DEF(__NR_ohoscapget, SysCapGet, UINT32, ARG_NUM_2) 130 SYSCALL_HAND_DEF(__NR_ohoscapset, SysCapSet, UINT32, ARG_NUM_1) 131 #endif 132 /* 新增系统调用 */ 133 SYSCALL_HAND_DEF(__NR_new_syscall_sample, SysNewSyscallSample, void, ARG_NUM_1) 134 ... 135 ``` 136 1374. 在内核中新增内核该系统调用对应的处理函数 138 如下所示,在kernel/liteos_a/syscall/los_syscall.h中,SysNewSyscallSample为新增系统调用的内核处理函数声明: 139 140 141 ``` 142 ... 143 /* 当前现有的系统调用内核处理函数声明清单 */ 144 extern int SysClockSettime64(clockid_t clockID, const struct timespec64 *tp); 145 extern int SysClockGettime64(clockid_t clockID, struct timespec64 *tp); 146 extern int SysClockGetres64(clockid_t clockID, struct timespec64 *tp); 147 extern int SysClockNanoSleep64(clockid_t clk, int flags, const struct timespec64 *req, struct timespec64 *rem); 148 extern int SysTimerGettime64(timer_t timerID, struct itimerspec64 *value); 149 extern int SysTimerSettime64(timer_t timerID, int flags, const struct itimerspec64 *value, struct itimerspec64 *oldValue); 150 /* 新增的系统调用内核处理函数声明 */ 151 extern void SysNewSyscallSample(int num); 152 ... 153 ``` 154 155 新增的系统调用的内核处理函数实现如下: 156 157 ``` 158 include "los_printf.h" 159 ... 160 /* 新增系统调用内核处理函数的实现 */ 161 void SysNewSyscallSample(int num) 162 { 163 PRINTK("kernel mode: num = %d\n", num); 164 return; 165 } 166 ``` 167 168 169**结果验证:** 170 171 172用户态程序调用newSyscallSample(10)接口,得到输出结果如下: 173 174 175 176``` 177/* 用户态接口与内核态接口均有输出,证明系统调用已使能 */ 178user mode: num = 10 179kernel mode: num = 10 180``` 181