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

ARM linux系统调用的实现原理

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x

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

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

4 E/ `" k1 Y; E# j1 G

at91rm9200处理器对应的linux2.4.19内核系统调用对应的软中断定义如下:
6 R. o0 `3 h3 Q: H/ r* Q7 F8 s' z#if defined(__thumb__) //thumb模式* Q& d  B, H" u" G
#define __syscall(name) /
/ J- w) `" R/ U1 e! f3 e"push {r7}/n/t" /+ N1 F" i) |/ I( z) [% U
"mov r7, #" __sys1(__NR_##name) "/n/t" /
9 r- ]( y6 e  `' U. ]$ m"swi 0/n/t" /* e/ Y$ X4 N. e% ]! e1 T; Y7 V& w' q
"pop {r7}"  x1 y* e$ m7 x. V# T" u
#else //ARM模式
7 s/ l, B0 ?3 e8 _8 o8 D5 z#define __syscall(name) "swi/t" __sys1(__NR_##name) "/n/t") M& B) B# Y  ^, P$ g$ N, w
#endif
6 |4 f0 r  ]# ^9 ~( p0 C- Q' L: t9 \- G+ H- e
#define __sys2(x) #x
, {) t1 r- z8 C, O) v4 i! ^#define __sys1(x) __sys2(x)
2 S4 w5 K/ n% x& r#define __NR_SYSCALL_BASE 0x900000 //此为OS_NUMBER << 20运算值
' d# l6 M4 e" L) m#define __NR_open (__NR_SYSCALL_BASE+ 5) //0x900005

5 Z( d- o+ p' H

举一个例子来说: 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在表中对应的顺序号为
/ x' i2 e8 @9 Q3 _* M0 ]; v- m__syscall_start:! l4 K* ]8 c& n# P7 ^; I
...
- h  d! ^' [& B9 h.long SYMBOL_NAME(sys_open) //第5个" u3 y2 z9 N& ]% r: j% H2 `( `
...

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

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

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

include/asm-arm/unistd.h定义了系统调用的调用号规则
& o) z' t8 l, D2 k9 `vector_swi定义在arch/arm/kernel/entry-common.S7 V% `5 W3 G" N  J
vector_IRQ定义在arch/arm/kernel/entry-armv.S# ]6 C- y, u$ e; }2 o/ ?2 N
vector_FIQ定义在arch/arm/kernel/entry-armv.S4 F5 G( a' F# N1 a. {
arch/arm/kernel/entry-common.S中对sys_call_table进行了定义:
: `+ w- K2 P: n1 }4 H.type sys_call_table, #object
, h; l0 j- L+ }7 ]2 {- S, _5 s8 C  ZENTRY(sys_call_table)
" U( A  r, G# h* j! ~#include "calls.S" //将calls.S中的内容顺序链接到这里" j1 d0 z0 B# q0 M0 I* I) G
源程序:+ j2 c. A$ R: F) h$ p8 h
ENTRY(vector_swi)
! I' b  E; ?* j5 j6 Z7 k9 wsave_user_regs! E2 C: x  E% \* u2 P
zero_fp
' P( ~6 g3 i% Cget_scno //将[lr,#-4]中的中断号转储到scno(r7)  i, R0 N9 B: e7 L0 i" i+ B+ p
arm710_bug_check scno, ip$ l" _6 L0 D( }9 o+ g3 b8 s& m
#ifdef CONFIG_ALIGNMENT_TRAP+ U( g; F4 S) I$ A# V  L
ldr ip, __cr_alignment
8 O$ y% N1 R" Z+ hldr ip, [ip]
  R' Q/ W( J7 o$ ^3 h4 n6 |mcr p15, 0, ip, c1, c0        @ update control register; w" U( M/ e; c% }
#endif
$ j* G( f$ r; S! ^8 ]$ Z" Kenable_irq ip
; u5 K. P9 B5 b2 i
, ]8 a5 Y2 ?, t" E3 r- Zstr r4, [sp, #-S_OFF]!        @ push fifth arg
* v! |. q, P) ^: H  E" ~1 j/ I* T/ ]6 G
get_current_task tsk( |: V: C8 J4 N  J' I% l& [! Q
ldr ip, [tsk, #TSK_PTRACE]        @ check for syscall tracing
2 {5 i( `" m, J  `5 K5 lbic scno, scno, #0xff000000        @ mask off SWI op-code- T& N; ~: a1 D$ {7 W6 ^& y8 u
//#define OS_NUMBER 9[entry-header.S]! |" A1 Z. l- B  j& z' \; R
//所以对于上面示例中open系统调用号scno=0x900005( G& d. t# {  c; X5 }
//eor scno,scno,#0x900000
* W8 \& J$ G: w$ m- X4 `//之后scno=0x053 N, {7 l+ [- w# I' d' B, B% D$ j3 O
eor scno, scno, #OS_NUMBER << 20        @ check OS number4 z0 d% G* |  i3 W& N
//sys_call_table项为calls.S的内容) v) W# y* @+ z5 l
adr tbl, sys_call_table        @ load syscall table pointer! U) w( i& E7 }+ f( i3 B; I+ s. j
tst ip, #PT_TRACESYS        @ are we tracing syscalls?
$ I) A- P+ P! }$ M% U! U; zbne __sys_trace; r7 U2 v$ c! ^

& Q" \! e  m: g6 Sadrsvc al, lr, ret_fast_syscall        @ return address
2 q: H: ]: h1 zcmp scno, #NR_syscalls        @ check upper syscall limit( L  n# r* d4 j2 B
//执行sys_open函数
* ]6 U0 L& B6 A6 Bldrcc pc, [tbl, scno, lsl #2]        @ call sys_* routine$ B0 Q: ]7 d2 a( u* k1 |3 o% K/ r
add r1, sp, #S_OFF2 {. K+ o) s  R! I
2: mov why, #0        @ no longer a real syscall( ]/ P8 e1 h7 m: f
cmp scno, #ARMSWI_OFFSET: w6 `, P* n* K5 l& k5 R
eor r0, scno, #OS_NUMBER << 20        @ put OS number back
! u, s7 ?, q! o% d1 z1 J1 gbcs SYMBOL_NAME(arm_syscall) + y  a1 R% X* ]- w! B9 a( V
b SYMBOL_NAME(sys_ni_syscall)        @ not private func
* g/ P! T; u1 q/*0 `' D  c; L/ ~& e3 m& d0 x' }
* This is the really slow path. We're going to be doing1 Q) K/ d9 P: E( ?; D- y& z
* context switches, and waiting for our parent to respond." L6 t1 X: r: }" D9 o* a/ |" ^
*/1 o0 m) j: d  V  R$ O
__sys_trace:' I. M/ Q; x+ z0 \8 }
add r1, sp, #S_OFF. k( W# D7 t( }  y5 ]7 i6 v+ G' K$ U% n' g
mov r0, #0        @ trace entry [IP = 0]
' T9 w# u' O8 W6 Pbl SYMBOL_NAME(syscall_trace)
* ?- P. u8 T5 X/*
# c' x* D$ ^+ E8 y//2007-07-01 gliethttp [entry-header.S]
7 J' ^8 o9 \- ]7 `//Like adr, but force SVC mode (if required)$ n' e' T% P, u! s
.macro adrsvc, cond, reg, label0 W8 ^. O0 v* ?' [" o2 T2 }
adr/cond /reg, /label
: ]" ?6 `9 H  }.endm
6 F& p- ]4 e" C& p//对应反汇编:$ U6 c( C# L' m1 y; ]2 m% {
//add lr, pc, #16 ; lr = __sys_trace_return
% s  W: `( B: |) I. A*/3 n0 o/ `# L  l' \/ o
adrsvc al, lr, __sys_trace_return        @ return address
8 F5 j" B8 w$ d/ v( o- Z. X" Zadd r1, sp, #S_R0 + S_OFF        @ pointer to regs# b% _4 Z0 ^# k
cmp scno, #NR_syscalls        @ check upper syscall limit
) W6 c9 K6 S$ Y) j5 x* eldmccia r1, {r0 - r3}        @ have to reload r0 - r37 b  p6 ~' s( k3 s% w# L
ldrcc pc, [tbl, scno, lsl #2]        @ call sys_* routine
) {) ]( Z1 q1 V! Hb 2b- [0 y! c! }* A% ^# F, w) N$ ~

; r" i4 z9 h; E* I( r__sys_trace_return:
" s2 V$ ?. D% [str r0, [sp, #S_R0 + S_OFF]!        @ save returned r0
" _: P0 c: b, J  N3 j# C* emov r1, sp$ `+ {$ t5 s; ?
mov r0, #1        @ trace exit [IP = 1]. u. p0 a% c% G9 Y
bl SYMBOL_NAME(syscall_trace)
. G/ |' J1 ]+ j! @0 ?3 Eb ret_disable_irq
: Z4 B% E" V% T4 Z: w4 E+ P: s; v% E+ |( _
.align 5
( Y  B* v# r! o$ ]: g- b' s#ifdef CONFIG_ALIGNMENT_TRAP
8 h( J/ Q  b6 X5 e" c8 F.type __cr_alignment, #object
2 g. E5 ?) U( v  a, I! n; k+ B  p9 K, d__cr_alignment:
* j1 B) ^* t  M) u.word SYMBOL_NAME(cr_alignment)
9 c; {% X* E# G: F0 Q1 P% U. J, Z#endif- ]9 i- q; v) a7 P# Z
.type sys_call_table, #object
" }4 r: C: U* x" j. q' G. d" @% gENTRY(sys_call_table)
! r* j& S# v* b#include "calls.S"

5 _0 C, Y2 G8 @0 N

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-6-26 15:27 , Processed in 0.093750 second(s), 23 queries , Gzip On.

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

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

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