|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
( R# q5 q/ J- \! L大家都知道linux的应用程序要想访问内核必须使用系统调用从而实现从usr模式转到svc模式。下面咱们看看它的实现过程。. c, V r& {( ~8 W+ Y% M D1 B
8 I4 u5 ^: F& q: M8 W; Y
系统调用是os操作系统提供的服务,用户程序通过各种系统调用,来引用内核提供的各种服务,系统调用的执行让用户程序陷入内核,该陷入动作由swi软中断完成。( b( s8 ^5 |0 r
/ n6 `. q9 Y5 J3 `0 @* v7 ]0 \2 c
at91rm9200处理器对应的linux2.4.19内核系统调用对应的软中断定义如下:9 o, L: M0 M6 w& P+ e5 b7 j
#if defined(__thumb__) //thumb模式: x/ |+ A. o3 q) ]
#define __syscall(name) /
2 u. Q# r3 f* V"push {r7}/n/t" /
. k9 [8 u/ H% v3 k! P k2 T* q"mov r7, #" __sys1(__NR_##name) "/n/t" /: N9 x2 D1 I2 x+ l2 J, E3 ~
"swi 0/n/t" /
0 _+ k. Z5 t6 x) L8 n& P. c8 p"pop {r7}"
6 N2 J. g3 x0 |$ t D4 l#else //ARM模式& ]+ C% K4 y" v' \/ D# n
#define __syscall(name) "swi/t" __sys1(__NR_##name) "/n/t"( \8 S; Z8 {! Z D* h5 _. ^
#endif1 L; g3 }. Y. ?" x+ y
$ h+ t+ K; T, F: u# M3 o. d
#define __sys2(x) #x
4 s& s+ ~5 Z. ~' y( k/ D. }#define __sys1(x) __sys2(x)
# u& u8 ]+ [# F( q1 b, }; ^: P#define __NR_SYSCALL_BASE 0x900000 //此为OS_NUMBER << 20运算值
: D0 G3 t9 H4 d* o#define __NR_open (__NR_SYSCALL_BASE+ 5) //0x900005
- m. m L; X# h" a( m$ J' A$ H1 L
$ b. y: H) H& B2 x3 g- @/ W7 p9 r
' g2 x9 I8 f) b
/ C s% V7 B3 q8 p- J1 K- ?. w举一个例子来说: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在表中对应的顺序号为
1 Y; _; r& o0 H" f( p__syscall_start:
- L/ g: l2 X5 b1 p6 |...
5 E! A1 t' {- P8 q+ U1 w* v.long SYMBOL_NAME(sys_open) //第5个
; z" m) U: Y Z5 R9 k, G3 Q...2 u! J* A8 `% j8 g$ k& t% U
/ ~5 o, L( R U7 k$ b
将sys_call_table[5]中内容传给pc,系统进入sys_open函数,处理实质的open动作9 X8 ?+ o+ @/ K' A
3 d" ~! V- s) O; N注:用到的一些函数数据所在文件,如下所示 \6 w/ r# F2 R; F* ?
- C+ g: E! _0 g/ m0 y h( o' N0 A
arch/arm/kernel/calls.S声明了系统调用函数
% b- _7 N7 k5 p6 O$ Y( p, o
9 w% `0 ~: J9 J Y3 R. W, O1 r2 L/ Winclude/asm-arm/unistd.h定义了系统调用的调用号规则4 W+ _. F% k0 E5 u v; n
vector_swi定义在arch/arm/kernel/entry-common.S$ M ]6 d# Y. _5 ?8 E" Z; X
vector_IRQ定义在arch/arm/kernel/entry-armv.S
1 V9 h7 A+ {& X* ^& U; M; Yvector_FIQ定义在arch/arm/kernel/entry-armv.S
4 J& q0 r! k* b. Z5 W" N8 ]arch/arm/kernel/entry-common.S中对sys_call_table进行了定义:! n4 @. m% R# _6 S& j: E/ b
.type sys_call_table, #object
3 ~, [# h! m9 _' G/ AENTRY(sys_call_table)1 a- A( q$ |# \, v$ n/ Z
#include "calls.S" //将calls.S中的内容顺序链接到这里
! F& p" N; ~6 g3 R) Y7 \2 ~! x源程序:2 \) v7 M; V- I( C: Z" I
ENTRY(vector_swi)3 \' O3 }" c& Q+ `" i
save_user_regs
% d9 A! A9 ]1 ]zero_fp3 d& f' W% `& t
get_scno //将[lr,#-4]中的中断号转储到scno(r7)
6 x9 j7 C! G) |* B( a% Darm710_bug_check scno, ip! i3 v/ w' ~6 u
#ifdef CONFIG_ALIGNMENT_TRAP
. M; P1 _ I" g# L# Y. m5 h0 Y+ f& ildr ip, __cr_alignment
, u# q& l! t! _ldr ip, [ip]
1 t6 D0 n* B8 I' \( M) R2 p" `mcr p15, 0, ip, c1, c0 @ update control register. J3 P# Q: O9 B' \$ J
#endif
1 d/ R g6 j N6 Y; ~; Lenable_irq ip9 G3 d) f) A9 I2 }
3 a, Q& e- Z' c7 H w1 c" l y* B
str r4, [sp, #-S_OFF]! @ push fifth arg, V: k# C* h3 }
9 |1 O) h0 W1 L, R
get_current_task tsk1 [5 F& P' j. T' }( ^2 }
ldr ip, [tsk, #TSK_PTRACE] @ check for syscall tracing
0 ^$ |9 a( U# p9 Ubic scno, scno, #0xff000000 @ mask off SWI op-code
; n& H4 V) P1 t- u% }//#define OS_NUMBER 9[entry-header.S]- t1 K2 B/ I% o3 p$ Q; l" X. o/ q
//所以对于上面示例中open系统调用号scno=0x900005. s1 M4 y1 t! R& N) J" A+ a0 b" K9 B
//eor scno,scno,#0x900000
0 J6 `# Y, p, ]+ G//之后scno=0x05
' T( S# W" L8 D- m% o; Z- ^eor scno, scno, #OS_NUMBER << 20 @ check OS number
M) e7 I. Q$ _5 q, A# `% r1 {! {- z//sys_call_table项为calls.S的内容
: v. G ~: e& [; a; ladr tbl, sys_call_table @ load syscall table pointer' }) }8 E! y2 i4 \
tst ip, #PT_TRACESYS @ are we tracing syscalls?
% P2 u$ K6 I5 f4 ?) z) ]bne __sys_trace# C* ^- [# K+ s4 E
" |* _3 A& ]9 u% [
adrsvc al, lr, ret_fast_syscall @ return address
3 B o( y5 N3 `5 Bcmp scno, #NR_syscalls @ check upper syscall limit
9 ~6 g. N( Q3 L2 ~" ]# I( U//执行sys_open函数) j( A! ], X- x4 Q6 Y; o
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine) s& f/ F% P' M( P
add r1, sp, #S_OFF
8 l' f+ B4 U2 v7 S- y( M' f2: mov why, #0 @ no longer a real syscall5 M- C$ v" \0 I
cmp scno, #ARMSWI_OFFSET
- f/ q3 Y8 [, J7 G( Neor r0, scno, #OS_NUMBER << 20 @ put OS number back& R' M9 _/ w4 j3 C4 J3 G. K
bcs SYMBOL_NAME(arm_syscall) & `& k6 c' ~2 s1 M" c; |, l0 y$ W
b SYMBOL_NAME(sys_ni_syscall) @ not private func8 B- l4 q- a$ Z6 s2 P8 Y/ S1 t# D
/*1 E' \. Z' _* G$ C7 A6 L8 B: t/ x
* This is the really slow path. We're going to be doing( G i: W; V4 @+ S$ Q
* context switches, and waiting for our parent to respond.- N* x* T1 e X! O3 u- C- M: q
*/
, q9 ~) J+ {& M* K. [__sys_trace:
, E+ f5 c! F' B, G& j( k& [% dadd r1, sp, #S_OFF
8 n* a- b+ i0 @! C. k& [, U+ R7 T7 smov r0, #0 @ trace entry [IP = 0]
/ O7 w* c2 k0 [; Jbl SYMBOL_NAME(syscall_trace)5 e% o1 S e7 O! ^5 Y
/*
" o# j& g1 L8 q' P//2007-07-01 gliethttp [entry-header.S]
6 T' z! R* j; p/ c. |, |//Like adr, but force SVC mode (if required)5 N2 r- C% i2 S6 T# Y* g0 s
.macro adrsvc, cond, reg, label. C1 Y0 D. S& h) p, B
adr/cond /reg, /label
4 R/ S) e7 R4 _( c5 O' x2 P.endm4 |/ b/ S1 y' \% {7 {
//对应反汇编:8 Z# Y! L0 m9 w, O
//add lr, pc, #16 ; lr = __sys_trace_return
: }% F3 u4 V- ?*/4 l8 q; m) x0 J& z5 @' Z3 R
adrsvc al, lr, __sys_trace_return @ return address' a* r8 g% L' E% x
add r1, sp, #S_R0 + S_OFF @ pointer to regs" u6 S7 s" ~) L$ i# U& {
cmp scno, #NR_syscalls @ check upper syscall limit
9 T5 V2 x/ |% g7 E* i% r3 P' Nldmccia r1, {r0 - r3} @ have to reload r0 - r3
6 F: T# M/ S5 K. t* U2 ]4 I- ~ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
5 N# ^ l$ s! ]% O; _b 2b& s% K4 \, Q" }$ I7 m4 j& {/ A
3 q8 a* `6 `# U- Y+ O7 y
__sys_trace_return:
% S5 D/ b ]: l& k9 s% u; Mstr r0, [sp, #S_R0 + S_OFF]! @ save returned r0" h" m1 j% r+ T4 T0 {7 J5 ?
mov r1, sp" l, J1 D2 I6 n4 k: k t9 t' r
mov r0, #1 @ trace exit [IP = 1]
7 E G3 U s9 ?# I+ ] q: `* `bl SYMBOL_NAME(syscall_trace)
3 ~0 G, m+ M! ?# r/ J+ pb ret_disable_irq* Q6 X9 c' ^0 g" L
; ?0 [) Z2 Y+ ]
.align 5
* X. [. E, l* g3 n1 P/ N) K# P#ifdef CONFIG_ALIGNMENT_TRAP
" L6 v# C: i( w! ?1 m, J& d.type __cr_alignment, #object7 L, P' z6 ?9 {$ a- J
__cr_alignment:3 Y: }# j/ \/ F+ W+ Y4 e! u/ N" J+ Q
.word SYMBOL_NAME(cr_alignment)1 x; T: G4 ]) _' [
#endif
, K0 V8 l% m! ^+ h/ W& F.type sys_call_table, #object& {- F3 ~6 @' x0 N4 C) k
ENTRY(sys_call_table)7 |' ^/ K- r3 [$ X4 ?, i
#include "calls.S"
5 u9 b, s: h# O9 C$ Y% N( f5 e
: l5 o7 L3 D! V4 b4 x |
|