您的位置 首页 嵌入式

Arm linux 体系调用剖析

Armlinux系统调用分析概述操作系统为在用户态运行的进程与硬件设备进行交互,提供操作系统的系统服务,提供了一组接口。在应用程序和硬件之…

Armlinux体系调用剖析
概述

操作体系为在用户态运转的进程与硬件设备进行交互,供给操作体系的体系服务,供给了一组接口。在应用程序和硬件之间,内核供给的体系服务设置一个额外层具有许多长处。

首要,这使得编程愈加简略,把用户从学习硬件设备的初级编程特性中解放出来。

其次,这极大地提高了体系的安全性,由于内核在企图满意某个恳求之前在接口级就能够查看这种恳求的正确性。

最终,更重要的是这些接口使得程序具有可移植性,由于只需内核所供给的一组接口相同,那么在任一内核之上就能够正确地编译和履行程序。

ARMLinux体系运用SWI指令来从用户空间进入内核空间,仍是先让咱们了解下这个SWI指令吧。SWI指令用于发生软件中止,然后实现从用户形式到管理形式的改换,CPSR保存到管理形式的SPSR,履行转移到SWI向量。在其他形式下也可运用SWI指令,处理器同样地切换到管理形式。指令格局如下:

SWI{cond}immed_24

其间:

immed_2424位当即数,值为从0——16777215之间的整数。

运用SWI指令时,一般运用以下两种办法进行参数传递,SWI反常处理程序能够供给相关的服务,这两种办法均是用户软件协议。

1)指令中24位的当即数指定了用户恳求的服务类型,参数经过通用寄存器传递。SWI反常处理程序要经过读取引起软件中止的SWI指令,以获得24为当即数。如:

MOVR0,#34

SWI12

2)指令中的24位当即数被疏忽,用户恳求的服务类型由寄存器R0的值决议,参数经过其他的通用寄存器传递。如:

MOVR0,#12

MOVR1,#34

SWI0

ArmLinux内核处理体系调用

  1. 在剖析arm中止处理进程中咱们提到过arm架构中的反常处理向量表,其间有一个地址便是处理swi软件中止的进口。
  2. .globl __vectors_start
  3. __vectors_start:
  4. swi SYS_ERROR0:
  5. b vector_und + stubs_offset
  6. ldr pc, .LCvswi + stubs_offset
  7. b vector_pabt + stubs_offset
  8. b vector_dabt + stubs_offset
  9. b vector_addrexcptn + stubs_offset
  10. b vector_irq + stubs_offset
  11. b vector_fiq + stubs_offset
  12. .globl __vectors_end:
  13. __vectors_end:
  14. Cpu履行上面赤色指令之后跳转到entry-common.s履行vector_swi处的指令,该函数便是内核中处理体系调用的进口。

  1. 在用户态调用swi指令,cpu从user状况切换到svc状况。首要需求履行的便是保存cpu现场,这样才能在堕入内核态履行了相应的体系调用处理进程之后,康复cpu用户态的状况,从头履行用户态进程。
  2. ENTRY(vector_swi)
  3. sub sp, sp, #S_FRAME_SIZE
  4. stmia sp, {r0 – r12} @ Calling r0 – r12
  5. add r8, sp, #S_PC
  6. stmdb r8, {sp, lr}^ @ Calling sp, lr
  7. mrs r8, spsr @ called from non-FIQ mode, so ok.
  8. str lr, [sp, #S_PC] @ Save calling PC
  9. str r8, [sp, #S_PSR] @ Save CPSR
  10. str r0, [sp, #S_OLD_R0] @ Save OLD_R0
  11. zero_fp
  12. BLANK();
  13. DEFINE(S_R0, offsetof(struct pt_regs, ARM_r0));
  14. DEFINE(S_R1, offsetof(struct pt_regs, ARM_r1));
  15. DEFINE(S_R2, offsetof(struct pt_regs, ARM_r2));
  16. DEFINE(S_R3, offsetof(struct pt_regs, ARM_r3));
  17. DEFINE(S_R4, offsetof(struct pt_regs, ARM_r4));
  18. DEFINE(S_R5, offsetof(struct pt_regs, ARM_r5));
  19. DEFINE(S_R6, offsetof(struct pt_regs, ARM_r6));
  20. DEFINE(S_R7, offsetof(struct pt_regs, ARM_r7));
  21. DEFINE(S_R8, offsetof(struct pt_regs, ARM_r8));
  22. DEFINE(S_R9, offsetof(struct pt_regs, ARM_r9));
  23. DEFINE(S_R10, offsetof(struct pt_regs, ARM_r10));
  24. DEFINE(S_FP, offsetof(struct pt_regs, ARM_fp));
  25. DEFINE(S_IP, offsetof(struct pt_regs, ARM_ip));
  26. DEFINE(S_SP, offsetof(struct pt_regs, ARM_sp));
  27. DEFINE(S_LR, offsetof(struct pt_regs, ARM_lr));
  28. DEFINE(S_PC, offsetof(struct pt_regs, ARM_pc));
  29. DEFINE(S_PSR, offsetof(struct pt_regs, ARM_cpsr));
  30. DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0));
  31. DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
  32. BLANK();

  1. ldr r10, [lr, #-4] @ get SWI instruction
  2. 之后,将swi指令保存在r10寄存器中
  3. enable_irq
  4. get_thread_info tsk
  5. adr tbl, sys_call_table @ load syscall table pointer
  6. ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing
  7. 敞开中止,将thread info结构的指针保存在tsk,将sys_call_table的地址保存在tbl中,将thread info结构中的flag保存ip中。
  8. scno .req r7 @ syscall number
  9. tbl .req r8 @ syscall table pointer
  10. why .req r8 @ Linux syscall (!= 0)
  11. tsk .req r9 @ current thread_info

  1. bics r10, r10, #0xff000000
  2. eorne scno, r10, #__NR_OABI_SYSCALL_BASE
  3. ldrne tbl, =sys_oabi_call_table
  4. #elif !defined(CONFIG_AEABI)
  5. bic scno, scno, #0xff000000 @ mask off SWI op-code
  6. eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
  7. #endif
  8. 查看swi指令中带的中止号是不是为0,假如不等于零阐明是是old ABI办法调用的体系调用,这时将sys_oabi_call_table的地址载入到tbl中,一起得到体系调用的中止号,保存在scno中。假如swi指令中带点中止号为0,阐明体系调用是运用scno寄存器传递中止号的。运用异或指令,将__NR_SYSCALL_BASE清除去,得到实践的体系恳求号(体系调用号界说为__NR_SYSCALL_BASE+x)。

  1. stmdb sp!, {r4, r5} @ push fifth and sixth args
  2. tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
  3. bne __sys_trace
  4. 假如进程带有syscall trace标志就调用sys_trace,这处应该是作为调试用的。
  5. cmp scno, #NR_syscalls @ check upper syscall limit
  6. adr lr, ret_fast_syscall @ return address
  7. ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
  8. 假如体系调用号,不大于NR_syscalls,就跳转到体系调用函数去履行ldrcc pc, [tbl, scno, lsl #2]

总结

Arm体系调用的简略概述。首要是用户态履行swi指令,swi指令使得cpu堕入svc状况,并跳转到固定地址去履行体系调用处理进程。用户态经过两种办法传递给内核履行体系调用的体系调用号。内核履行体系调用处理进程,首要保存cpu现场,之后会获取到体系调用号,以体系调用地址表的基地址,加体系调用号做偏移,跳转到相应的体系调用例程做相应的处理。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/277358.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部