作者:刘洪涛,华清远见嵌入式学院讲师。

大家都知道linux的应用程序要想访问内核必须使用系统调用从而实现从usr模式转到svc模式。下面咱们看看它的实现过程。

系统调用是os操作系统提供的服务,用户程序通过各种系统调用,来引用内核提供的各种服务,系统调用的执行让用户程序陷入内核,该陷入动作由swi软中断完成。

at91rm9200处理器对应的linux2.4.19内核系统调用对应的软中断定义如下:
#if defined(__thumb__) //thumb模式
#define __syscall(name) /
"push {r7}/n/t" /
"mov r7, #" __sys1(__NR_##name) "/n/t" /
"swi 0/n/t" /
"pop {r7}"
#else //arm模式
#define __syscall(name) "swi/t" __sys1(__NR_##name) "/n/t"
#endif

#define __sys2(x) #x
#define __sys1(x) __sys2(x)
#define __NR_SYSCALL_BASE 0x900000 //此为OS_NUMBER << 20运算值
#define __NR_open (__NR_SYSCALL_BASE+ 5) //0x900005

举一个例子来说:open系统调用,库函数最终会调用__syscall(open),宏展开之后为swi #__NR_open,即,swi #0x900005触发中断,中断号0x900005存放在[lr,#-4]地址中,处理器跳转到arch/arm/kernel/entry-common.S中vector_swi读取[lr,#-4]地址中的中断号,之后查询arch/arm/kernel/entry-common.S中的sys_call_table系统调用表,该表内容在arch/arm/kernel/calls.S中定义,__NR_open在表中对应的顺序号为
__syscall_start:
...
.long SYMBOL_NAME(sys_open) //第5个
...

将sys_call_table[5]中内容传给pc,系统进入sys_open函数,处理实质的open动作

注:用到的一些函数数据所在文件,如下所示

arch/arm/kernel/calls.S声明了系统调用函数

include/asm-arm/unistd.h定义了系统调用的调用号规则
vector_swi定义在arch/arm/kernel/entry-common.S
vector_IRQ定义在arch/arm/kernel/entry-armv.S
vector_FIQ定义在arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S中对sys_call_table进行了定义:
.type sys_call_table, #object
ENTRY(sys_call_table)
#include "calls.S" //将calls.S中的内容顺序链接到这里
源程序:
ENTRY(vector_swi)
save_user_regs
zero_fp
get_scno //将[lr,#-4]中的中断号转储到scno(r7)
arm710_bug_check scno, ip
#ifdef CONFIG_ALIGNMENT_TRAP
ldr ip, __cr_alignment
ldr ip, [ip]
mcr p15, 0, ip, c1, c0        @ update control register
#endif
enable_irq ip

str r4, [sp, #-S_OFF]!        @ push fifth arg

get_current_task tsk
ldr ip, [tsk, #TSK_PTRACE]        @ check for syscall tracing
bic scno, scno, #0xff000000        @ mask off SWI op-code
//#define OS_NUMBER 9[entry-header.S]
//所以对于上面示例中open系统调用号scno=0x900005
//eor scno,scno,#0x900000
//之后scno=0x05
eor scno, scno, #OS_NUMBER << 20        @ check OS number
//sys_call_table项为calls.S的内容
adr tbl, sys_call_table        @ load syscall table pointer
tst ip, #PT_TRACESYS        @ are we tracing syscalls?
bne __sys_trace

adrsvc al, lr, ret_fast_syscall        @ return address
cmp scno, #NR_syscalls        @ check upper syscall limit
//执行sys_open函数
ldrcc pc, [tbl, scno, lsl #2]        @ call sys_* routine
add r1, sp, #S_OFF
2: mov why, #0        @ no longer a real syscall
cmp scno, #ARMSWI_OFFSET
eor r0, scno, #OS_NUMBER << 20        @ put OS number back
bcs SYMBOL_NAME(arm_syscall)
b SYMBOL_NAME(sys_ni_syscall)        @ not private func
/*
* This is the really slow path. We're going to be doing
* context switches, and waiting for our parent to respond.
*/
__sys_trace:
add r1, sp, #S_OFF
mov r0, #0        @ trace entry [IP = 0]
bl SYMBOL_NAME(syscall_trace)
/*
//2007-07-01 gliethttp [entry-header.S]
//Like adr, but force SVC mode (if required)
.macro adrsvc, cond, reg, label
adr/cond /reg, /label
.endm
//对应反汇编:
//add lr, pc, #16 ; lr = __sys_trace_return
*/
adrsvc al, lr, __sys_trace_return        @ return address
add r1, sp, #S_R0 + S_OFF        @ pointer to regs
cmp scno, #NR_syscalls        @ check upper syscall limit
ldmccia r1, {r0 - r3}        @ have to reload r0 - r3
ldrcc pc, [tbl, scno, lsl #2]        @ call sys_* routine
b 2b

__sys_trace_return:
str r0, [sp, #S_R0 + S_OFF]!        @ save returned r0
mov r1, sp
mov r0, #1        @ trace exit [IP = 1]
bl SYMBOL_NAME(syscall_trace)
b ret_disable_irq

.align 5
#ifdef CONFIG_ALIGNMENT_TRAP
.type __cr_alignment, #object
__cr_alignment:
.word SYMBOL_NAME(cr_alignment)
#endif
.type sys_call_table, #object
ENTRY(sys_call_table)
#include "calls.S"

如果您喜欢这篇文章,可以加华清远见老师为好友,单击以下链接即可:

http://student.csdn.net/invite.php?u=45153&c=8af704eb3cd8e773

(作者:华清远见嵌入式培训中心   www.embedu.org    www.farsight.com.cn  )

ARM linux系统调用的实现原理相关推荐

  1. linux系统调用的封装格式,ARM Linux系统调用的原理

    ARM Linux系统调用的原理ARM Linux系统调用的原理 操作系统为在用户态运行的进程与硬件设备进行交互提供了一组接口.在应用程序和硬件之间设置一个额外层具有很多优点.首先,这使得编程更加容易 ...

  2. linux中swi指令,Arm Linux系统调用流程详细解析SWI

    Unix系统通过向内核发出系统调用(system call)实现了用户态进程和硬件设备之间的大部分接口.系统调用是操作系统提供的服务,用户程序通过各种系统调用,来引用内核提供的各种服务,系统调用的执行 ...

  3. linux系统调用理解之摘录(3)

    Linux系统调用需要持续不断地深入理解,因此这里收集一些较好的博客,以便后续自己参考研究: (1)Linux 库函数与系统调用的关系与区别 https://www.cnblogs.com/liwei ...

  4. Linux系统调用(syscall)原理(转载)

    转载链接: http://gityuan.com/2016/05/21/syscall/ 先来个整体介绍: 系统调用工作原理: 一般情况下,用户进程是不能访问内核的.它既不能访问内核所在的内存空间,也 ...

  5. Linux 系统调用深思:从原理到实战

    Linux 系统调用揭秘:从原理到实战(Demystifying Linux System Calls: From Principles to Practice) 引言(Introduction) 系 ...

  6. Android 6.0 JNI原理分析 和 Linux系统调用(syscall)原理

    JNI原理 引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码: fram ...

  7. arm 模式 Linux,ARM Linux:usr模式转为svc模式的实现原理

    大家都知道linux的应用程序要想访问内核必须使用系统调用从而实现从usr模式转到svc模式.下面咱们看看它的实现过程. 系统调用是os操作系统提供的服务,用户程序通过各种系统调用,来引用内核提供的各 ...

  8. 操作系统原理,系统调用,系统调用与库函数API等函数之间的调用关系,功能与机制设计,系统调用的执行过程与Linux系统调用执行示例,不同操作系统下的PCB

    操作系统原理,系统调用,功能与机制设计,系统调用的执行过程与Linux系统调用执行示例,不同操作系统下的PCB 一.系统调用:操作系统功能调用,用户在编程时可以调用的操作系统功能. 1.系统调用是操作 ...

  9. 第四十一期-ARM Linux内核的系统调用(1)

    作者:罗宇哲,中国科学院软件研究所智能软件研究中心 上一期中我们介绍了工作队列相关的关键函数,这一期我们将介绍ARM Linux内核中的系统调用. 一.ARM Linux内核中的系统调用 在ARM L ...

最新文章

  1. 关于jenkins的安装及自动部署
  2. 算法提高课-搜索-Flood fill算法-AcWing 1106. 山峰和山谷:flood fill、bfs
  3. 扑克牌排序_巧用扑克牌搞定孩子的数学思维启蒙,聪明的妈妈都在玩这样的游戏...
  4. 手动添加ubuntu服务
  5. Actor生命周期理解
  6. Java日历compareTo()方法与示例
  7. 暴力推荐2:硬盘分区丢失之DiskGenius
  8. linux zip命令收藏
  9. 控制台输入聊天记录 输出到文件中保存 Day20
  10. 优秀课件笔记——财政学1
  11. Java进阶--Java垃圾回收机制全面解析
  12. 托马斯微积分第十一版_企业微服务第一部分
  13. 免费的文字转语音朗读 -API接口
  14. 微信小程序漏洞:可下载任意微信小游戏源代码(附赠源码)
  15. 八皇后算法—java
  16. 1、软件工程基础理论
  17. 笔记本电脑f11功能键_电脑的键盘上的F1至F12的功能分别是什么
  18. LaTex绘制跨行跨列的三线表
  19. 关于vue项目的seo问题
  20. 【数字图像处理】图像的数学变换之傅里叶变换

热门文章

  1. Type ‘HTMLElement | null‘ is not assignable to type ‘HTMLElement‘
  2. 人脸识别小区门禁系统_小区人脸识别门禁系统安全吗?
  3. 沐神-动手学深度学习-引言
  4. js仿google+分享新鲜事系统实例源码
  5. Java,配置Java环境
  6. python实操100例实例_python开发之list操作实例分析
  7. 沃美小镇电闪雷鸣 广宇连夜而来
  8. 媒体揭露互联网“账号黑市”:百倍暴利
  9. 台式计算机硬盘英寸,浅谈3.5英寸硬盘与2.5英寸硬盘的区别
  10. Springboot启动报错[ main] o.s.boot.SpringApplication: Application run failed