微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Arm linux 系统调用分析

Arm linux 系统调用分析

时间:11-09 来源:互联网 点击:
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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top