概述
操作系统为在用户态运行的进程与硬件设备进行交互,提供操作系统的系统服务,提供了一组接口。在应用程序和硬件之间,内核提供的系统服务设置一个额外层具有很多优点。
首先,这使得编程更加容易,把用户从学习硬件设备的低级编程特性中解放出来。
其次,这极大地提高了系统的安全性,因为内核在试图满足某个请求之前在接口级就可以检查这种请求的正确性。
最后, 更重要的是这些接口使得程序具有可移植性,因为只要内核所提供的一组接口相同,那么在任一内核之上就可以正确地编译和执行程序。
ARM Linux系统利用SWI指令来从用户空间进入内核空间,还是先让我们了解下这个SWI指令吧。SWI指令用于产生软件中断,从而实现从用户模式到管理模 式的变换,CPSR保存到管理模式的SPSR,执行转移到SWI向量。在其他模式下也可使用SWI指令,处理器同样地切换到管理模式。指令格式如下:
SWI{cond} immed_24
其中:
immed_24 24位立即数,值为从0——16777215之间的整数。
使用SWI指令时,通常使用以下两种方法进行参数传递,SWI异常处理程序可以提供相关的服务,这两种方法均是用户软件协定。
1) 指令中24位的立即数指定了用户请求的服务类型,参数通过通用寄存器传递。SWI异常处理程序要通过读取引起软件中断的SWI指令,以取得24为立即数。如:
MOV R0,#34
SWI 12
2) 指令中的24位立即数被忽略,用户请求的服务类型由寄存器R0的值决定,参数通过其他的通用寄存器传递。如:
MOV R0, #12
MOV R1, #34
SWI 0
Arm Linux内核处理系统调用
- 在分析arm中断处理过程中我们提到过arm架构中的异常处理向量表,其中有一个地址就是处理swi软件中断的入口。
- .globl __vectors_start
- __vectors_start:
- swi SYS_ERROR0:
- b vector_und + stubs_offset
- ldr pc, .LCvswi + stubs_offset
- b vector_pabt + stubs_offset
- b vector_dabt + stubs_offset
- b vector_addrexcptn + stubs_offset
- b vector_irq + stubs_offset
- b vector_fiq + stubs_offset
- .globl __vectors_end:
- __vectors_end:
- Cpu执行上面红色指令之后跳转到entry-common.s执行vector_swi处的指令,该函数就是内核中处理系统调用的入口。
- 在用户态调用swi指令,cpu从user状态切换到svc状态。首先需要执行的就是保存cpu现场,这样才能在陷入内核态执行了相应的系统调用处理过程之后,恢复cpu用户态的状态,重新执行用户态进程。
- ENTRY(vector_swi)
- sub sp, sp, #S_FRAME_SIZE
- stmia sp, {r0 - r12} @ Calling r0 - r12
- add r8, sp, #S_PC
- stmdb r8, {sp, lr}^ @ Calling sp, lr
- mrs r8, spsr @ called from non-FIQ mode, so ok.
- str lr, [sp, #S_PC] @ Save calling PC
- str r8, [sp, #S_PSR] @ Save CPSR
- str r0, [sp, #S_OLD_R0] @ Save OLD_R0
- zero_fp
- BLANK();
- DEFINE(S_R0, offsetof(struct pt_regs, ARM_r0));
- DEFINE(S_R1, offsetof(struct pt_regs, ARM_r1));
- DEFINE(S_R2, offsetof(struct pt_regs, ARM_r2));
- DEFINE(S_R3, offsetof(struct pt_regs, ARM_r3));
- DEFINE(S_R4, offsetof(struct pt_regs, ARM_r4));
- DEFINE(S_R5, offsetof(struct pt_regs, ARM_r5));
- DEFINE(S_R6, offsetof(struct pt_regs, ARM_r6));
- DEFINE(S_R7, offsetof(struct pt_regs, ARM_r7));
- DEFINE(S_R8, offsetof(struct pt_regs, ARM_r8));
- DEFINE(S_R9, offsetof(struct pt_regs, ARM_r9));
- DEFINE(S_R10, offsetof(struct pt_regs, ARM_r10));
- DEFINE(S_FP, offsetof(struct pt_regs, ARM_fp));
- DEFINE(S_IP, offsetof(struct pt_regs, ARM_ip));
- DEFINE(S_SP, offsetof(struct pt_regs, ARM_sp));
- DEFINE(S_LR, offsetof(struct pt_regs, ARM_lr));
- DEFINE(S_PC, offsetof(struct pt_regs, ARM_pc));
- DEFINE(S_PSR, offsetof(struct pt_regs, ARM_cpsr));
- DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0));
- DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
- BLANK();
- ldr r10, [lr, #-4] @ get SWI instruction
- 之后,将swi指令保存在r10寄存器中
- enable_irq
- get_thread_info tsk
- adr tbl, sys_call_table @ load syscall table pointer
- ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing
- 开启中断,将thread info结构的指针保存在tsk,将sys_call_table的地址保存在tbl中,将thread info结构中的flag保存ip中。
- scno .req r7 @ syscall number
- tbl .req r8 @ syscall table pointer
- why .req r8 @ Linux syscall (!= 0)
- tsk .req r9 @ current thread_info
- bics r10, r10, #0xff000000
- eorne scno, r10, #__NR_OABI_SYSCALL_BASE
- ldrne tbl, =sys_oabi_call_table
- #elif !defined(CONFIG_AEABI)
- bic scno, scno, #0xff000000 @ mask off SWI op-code
- eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
- #endif
- 检查swi命令中带的中断号是不是为0,如果不等于零说明是是old ABI方式调用的系统调用,这时将sys_oabi_call_table的地址载入到tbl中,同时得到系统调用的中断号,保存在scno中。如果swi指令中带点中断号为0,说明系统调用是利用scno寄存器传递中断号的。利用异或指令,将__NR_SYSCALL_BASE清除掉,得到实际的系统请求号(系统调用号定义为__NR_SYSCALL_BASE+x)。
- stmdb sp!, {r4, r5} @ push fifth and sixth args
- tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
- bne __sys_trace
- 如果进程带有syscall trace标志就调用sys_trace,这处应该是作为调试用的。
- cmp scno, #NR_syscalls @ check upper syscall limit
- adr lr, ret_fast_syscall @ return address
- ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
- 如果系统调用号,不大于NR_syscalls,就跳转到系统调用函数去执行ldrcc pc, [tbl, scno, lsl #2]
总结
Arm系统调用的简单概述。首先是用户态执行swi指令,swi指令使得cpu陷入svc状态,并跳转到固定地址去执行系统调用处理过程。用户态通过两种方法传递给内核执行系统调用的系统调用号。内核执行系统调用处理过程,首先保存cpu现场,之后会获取到系统调用号,以系统调用地址表的基地址,加系统调用号做偏移,跳转到相应的系统调用例程做相应的处理。
上一篇:arm linux 系统调用实现
下一篇:Arm Linux系统调用流程详细解析
推荐阅读最新更新时间:2024-03-16 14:57
设计资源 培训 开发板 精华推荐
- Allegro MicroSystems 在 2024 年德国慕尼黑电子展上推出先进的磁性和电感式位置感测解决方案
- 左手车钥匙,右手活体检测雷达,UWB上车势在必行!
- 狂飙十年,国产CIS挤上牌桌
- 神盾短刀电池+雷神EM-i超级电混,吉利新能源甩出了两张“王炸”
- 浅谈功能安全之故障(fault),错误(error),失效(failure)
- 智能汽车2.0周期,这几大核心产业链迎来重大机会!
- 美日研发新型电池,宁德时代面临挑战?中国新能源电池产业如何应对?
- Rambus推出业界首款HBM 4控制器IP:背后有哪些技术细节?
- 村田推出高精度汽车用6轴惯性传感器
- 福特获得预充电报警专利 有助于节约成本和应对紧急情况
- 或彻底摆脱电池厂商?整车企业自建电池厂成趋势
- 用于车载(符合 AEC-Q100)18V 操作驱动器 Tr 同步整流降压 DC/DC 的转换器
- Vishay推出新型汽车级接近传感器,压力感测分辨率高达20 µm
- Elektrobit 支持 BlackBerry QNX OS 构建基于 HPC 的车辆架构
- ACES 竞赛:半导体将指引汽车制造商到达终点线
- 动力电池大逆转:磷酸铁锂产量、装车量全面反超三元
- 英飞凌赋能Flex Power Modules全新开关式电容中间总线转换器, 为48V数据中心应用提供高功率密度
- 上汽通用五菱将推出“五菱芯片”
- WNEVC 2021 | 中国科学院物理研究所高级工程师俞海龙:全固态锂二次电池的技术挑战
- 全包裹式4轴桌面机械臂---小象码垛机械臂抢先正式发售!