找回密码
 注册
关于网站域名变更的通知
查看: 274|回复: 1
打印 上一主题 下一主题

ARM linux系统调用的实现原理

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-10-10 17:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x

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

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

7 u/ k5 z4 O9 l/ J

at91rm9200处理器对应的linux2.4.19内核系统调用对应的软中断定义如下:% f6 G3 y% _" t% R' Q
#if defined(__thumb__) //thumb模式; m, R' Q0 u( J% e
#define __syscall(name) /8 s, f. O6 i4 _
"push {r7}/n/t" /1 z5 t) Y6 t0 X: t3 x
"mov r7, #" __sys1(__NR_##name) "/n/t" /. t$ U' m& V' z3 y% d6 O- P( P
"swi 0/n/t" /
# `2 x3 P1 O2 J$ x8 V9 Y"pop {r7}"
% F- a( s' m; \#else //ARM模式
( ?  G8 Y) g/ d+ e' t#define __syscall(name) "swi/t" __sys1(__NR_##name) "/n/t"
$ ?7 E$ i2 q) O" @" G#endif
; C1 q" W! z1 ~5 u0 p# u+ X
; p& s- u) J3 N  I9 [4 C#define __sys2(x) #x) F3 q5 g. x' s% x* p
#define __sys1(x) __sys2(x)7 `6 V$ D5 x* @6 s
#define __NR_SYSCALL_BASE 0x900000 //此为OS_NUMBER << 20运算值- W2 {' D6 U2 \4 y# l2 \
#define __NR_open (__NR_SYSCALL_BASE+ 5) //0x900005

! }; n0 v5 z- R, C1 y

举一个例子来说: 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在表中对应的顺序号为  B$ R% R4 q4 u5 s" ?
__syscall_start:
0 @! w+ B% `* |: x0 n& a2 x...6 m9 L8 m( ~9 C
.long SYMBOL_NAME(sys_open) //第5个
; B6 Q3 U) W; ~. ]4 ~...

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

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

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

include/asm-arm/unistd.h定义了系统调用的调用号规则
- ^- C  h: P  ?7 Q/ nvector_swi定义在arch/arm/kernel/entry-common.S
* a  G9 }: d, S! dvector_IRQ定义在arch/arm/kernel/entry-armv.S/ N5 b% v+ @% A0 d0 n
vector_FIQ定义在arch/arm/kernel/entry-armv.S1 @. s  M$ p! a* P$ G6 y5 F
arch/arm/kernel/entry-common.S中对sys_call_table进行了定义:4 t$ B- k2 D" k  ?" T
.type sys_call_table, #object# E" H1 {; F0 n5 w
ENTRY(sys_call_table)
' v' p' |: P" j8 ?  R#include "calls.S" //将calls.S中的内容顺序链接到这里
$ u0 [- V. C( r; t! h9 W源程序:* e3 l! [  r% x4 \+ U+ B
ENTRY(vector_swi)0 y4 Q! y4 s9 }0 F' {. b
save_user_regs$ T* c+ ^, K1 Z* I6 e
zero_fp: N6 Z4 r6 g2 z& C1 t- l4 ^
get_scno //将[lr,#-4]中的中断号转储到scno(r7)/ C1 [# q4 b) l
arm710_bug_check scno, ip" k" e$ I# p, w
#ifdef CONFIG_ALIGNMENT_TRAP4 w* [3 P  ?4 _- I) ~: A
ldr ip, __cr_alignment2 x! l! K, ~# z9 b4 l. K
ldr ip, [ip]  a7 ~( {. c5 p3 }* U; |; C
mcr p15, 0, ip, c1, c0        @ update control register( z0 ]  k& j/ g; s8 f0 j, X2 J
#endif
6 ^* R' }, b1 E) genable_irq ip
- ]3 F1 G5 b% Y. N9 K  I" o! |; o9 m9 J9 N7 _; Y
str r4, [sp, #-S_OFF]!        @ push fifth arg
3 Q, u- G7 r* H9 V! m* J; B# b, s6 v* P. b  ?3 Z& b: x! I
get_current_task tsk
6 O' Y( h* y, D. @  [5 U+ q6 Zldr ip, [tsk, #TSK_PTRACE]        @ check for syscall tracing
4 k4 Q- o, n% B+ mbic scno, scno, #0xff000000        @ mask off SWI op-code
2 E, m% _2 }$ ^3 G//#define OS_NUMBER 9[entry-header.S]
% s: m" m4 D0 b//所以对于上面示例中open系统调用号scno=0x900005
8 {6 o# @; F6 b# Q/ x//eor scno,scno,#0x9000007 f/ x) R3 q* j* S3 a- C; W
//之后scno=0x05
) h1 z: I: b( p& P+ [8 o6 `! Teor scno, scno, #OS_NUMBER << 20        @ check OS number
+ d6 U5 q9 R' [3 M+ _$ c7 s//sys_call_table项为calls.S的内容
0 z) v8 k) Q3 r; C3 Hadr tbl, sys_call_table        @ load syscall table pointer
+ W% g1 G$ n! Z. _tst ip, #PT_TRACESYS        @ are we tracing syscalls?
/ i2 I# y4 C  qbne __sys_trace$ }8 O* `+ L/ `4 D6 M
: m9 v. f" ~3 u* K( U
adrsvc al, lr, ret_fast_syscall        @ return address# _; i. d8 m/ x! u
cmp scno, #NR_syscalls        @ check upper syscall limit' a* y7 `7 d. l$ T. H- Q. R; P3 D
//执行sys_open函数
+ q  e& o. d/ ]* q. Q. Rldrcc pc, [tbl, scno, lsl #2]        @ call sys_* routine7 G- g% K/ _; d' \+ ^) y
add r1, sp, #S_OFF; }) m4 ]& R# u9 i
2: mov why, #0        @ no longer a real syscall$ a- M  Y# d, V5 |
cmp scno, #ARMSWI_OFFSET0 C8 a+ p# y, Y( r# d
eor r0, scno, #OS_NUMBER << 20        @ put OS number back3 F) _/ g. }- H0 J8 Q, p
bcs SYMBOL_NAME(arm_syscall)
5 F7 {2 L9 a; j8 B8 ~3 Tb SYMBOL_NAME(sys_ni_syscall)        @ not private func
8 C% @& y  @1 ]! K/*! q  s2 c7 j  [8 J1 ^
* This is the really slow path. We're going to be doing
9 m$ `  {& r" g3 r  Y2 M5 t1 j* context switches, and waiting for our parent to respond.- Q# l4 Z* Z0 P
*/( i, G$ p2 X9 }" s" o& H+ r
__sys_trace:
) r9 f. l; N& c) M* |7 d8 Q5 yadd r1, sp, #S_OFF
2 g$ s% O3 {; o3 G5 `2 P1 P  A! Vmov r0, #0        @ trace entry [IP = 0]
$ K- N; g' r$ ^  Abl SYMBOL_NAME(syscall_trace)7 U2 E; q, A# g7 {# v; l% ]
/*
7 i# f: j: s$ Q2 [% j; ?4 T& m$ ~//2007-07-01 gliethttp [entry-header.S]' L8 J6 }1 V) f& r
//Like adr, but force SVC mode (if required)
! [! X4 @* U! s! @: f5 I( C.macro adrsvc, cond, reg, label8 ]( Z  M2 l1 q
adr/cond /reg, /label
5 b+ L) l/ k! e.endm- \, x# p1 ~) l5 I8 I9 i+ u6 o* V
//对应反汇编:5 {1 C6 l, t; C. j) W
//add lr, pc, #16 ; lr = __sys_trace_return) F: r( F' j) z0 d8 q
*/
8 i6 M0 ^; ?4 n( g  }adrsvc al, lr, __sys_trace_return        @ return address+ |% f9 W/ Q6 |$ k
add r1, sp, #S_R0 + S_OFF        @ pointer to regs' ?% n% k. _- @* u  x; N
cmp scno, #NR_syscalls        @ check upper syscall limit
6 t/ q3 b! V! R9 |% C, \! b+ [& Aldmccia r1, {r0 - r3}        @ have to reload r0 - r3
  X# e* J% }  W( H7 ]$ Vldrcc pc, [tbl, scno, lsl #2]        @ call sys_* routine9 y& _$ |  m% t* @5 C; e- w
b 2b
) G0 A! s/ Y! P4 g* n
' g3 b: |- V+ p) s# Z__sys_trace_return:2 v$ @/ }$ w) [3 s
str r0, [sp, #S_R0 + S_OFF]!        @ save returned r0% f- n; U9 v5 @6 E+ ?+ G
mov r1, sp8 ~7 y7 S3 p- X9 ^9 A
mov r0, #1        @ trace exit [IP = 1]
6 ?6 P* g! Z% K2 Z6 S$ y5 y; Xbl SYMBOL_NAME(syscall_trace)
" L8 C' `! g# \b ret_disable_irq% s* [, i- s6 d2 r

/ W- m) r: w/ q0 U.align 5# u  q3 h- _. R: D
#ifdef CONFIG_ALIGNMENT_TRAP: M% {! i  d% l* \& {
.type __cr_alignment, #object: s3 P% s+ r* y
__cr_alignment:
0 @4 D* u- C* K& P) m& }.word SYMBOL_NAME(cr_alignment)# j7 Q" S! A  E4 a, ?& i0 a6 g
#endif2 F! j) @8 s# m4 l1 B; i
.type sys_call_table, #object
; @( C' E6 U# [6 F, }ENTRY(sys_call_table)  G. V# e/ q" C( O5 `8 q5 {
#include "calls.S"

+ d5 ]5 H2 N: j: y

该用户从未签到

2#
发表于 2020-10-10 18:29 | 只看该作者
ARM linux系统调用的实现原理
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-11-24 21:19 , Processed in 0.156250 second(s), 24 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表