举一个例子来说pen系统调用,库函数最终会调用__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"
|