ARM Linux 系统调用过程(2)

/* Legacy ABI only, possibly thumb mode. */
 tst r8, #PSR_T_BIT   @ this is SPSR from save_user_regs
 addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in
 ldreq scno, [lr, #-4]

#else

/* Legacy ABI only. */
 ldr scno, [lr, #-4]   @ get SWI instruction
  A710( and ip, scno, #0x0f000000  @ check for SWI  )
  A710( teq ip, #0x0f000000      )
  A710( bne .Larm710bug      )

#endif

#ifdef CONFIG_ALIGNMENT_TRAP
 ldr ip, __cr_alignment
 ldr ip, [ip]
 mcr p15, 0, ip, c1, c0  @ update control register
#endif
 enable_irq

get_thread_info tsk

 adr tbl, sys_call_table  @ load syscall table pointer  #获取系统调用表的基地址
 ldr ip, [tsk, #TI_FLAGS]  @ check for syscall tracing

#if defined(CONFIG_OABI_COMPAT)
 /*
  * If the swi argument is zero, this is an EABI call and we do nothing.
  *
  * If this is an old ABI call, get the syscall number into scno and
  * get the old ABI syscall table address.
  */
 bics r10, r10, #0xff000000
 eorne scno, r10, #__NR_OABI_SYSCALL_BASE
 ldrne tbl, =sys_oabi_call_table
#elif !defined(CONFIG_AEABI)
 bic scno, scno, #0xff000000  @ mask off SWI op-code
 eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
#endif

stmdb sp!, {r4, r5}   @ push fifth and sixth args
 tst ip, #_TIF_SYSCALL_TRACE  @ are we tracing syscalls?
 bne __sys_trace

cmp scno, #NR_syscalls  @ check upper syscall limit
 adr lr, BSYM(ret_fast_syscall) @ return address
 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, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
 eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back
 bcs arm_syscall 
 b sys_ni_syscall   @ not private func

从上面可以看出,当CPU从中断向量表转到vector_swi 之后,完成了几件事情:1.取出系统调用号 2.根据系统调用号取出系统调用函数在系统调用表的基地址,得到一个系统调用函数的函数指针 3. 根据系统调用表的基地址和系统调用号,得到这个系统调用表里的项,每一个表项都是一个函数指针,把这个函数指针赋给PC , 则实现了跳转到系统调用函数。

系统调用表定义在:arch/arm/kernel/Calls.S

* This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  This file is included thrice in entry-common.S
 */
/* 0 */  CALL(sys_restart_syscall)
  CALL(sys_exit)
  CALL(sys_fork_wrapper)
  CALL(sys_read)
  CALL(sys_write)
/* 5 */  CALL(sys_open)
  CALL(sys_close)
  CALL(sys_ni_syscall)  /* was sys_waitpid */
  CALL(sys_creat)
  CALL(sys_link)
/* 10 */ CALL(sys_unlink)
  CALL(sys_execve_wrapper)
  CALL(sys_chdir)
  CALL(OBSOLETE(sys_time)) /* used by libc4 */
  CALL(sys_mknod)
/* 15 */ CALL(sys_chmod)
  CALL(sys_lchown16)
  CALL(sys_ni_syscall)  /* was sys_break */
  CALL(sys_ni_syscall)  /* was sys_stat */
  CALL(sys_lseek)
/* 20 */ CALL(sys_getpid)
  CALL(sys_mount)
  CALL(OBSOLETE(sys_oldumount)) /* used by libc4 */
  CALL(sys_setuid16)
  CALL(sys_getuid16)
/* 25 */ CALL(OBSOLETE(sys_stime))
  CALL(sys_ptrace)
  CALL(OBSOLETE(sys_alarm)) /* used by libc4 */
  CALL(sys_ni_syscall)  /* was sys_fstat */
  CALL(sys_pause)
/* 30 */ CALL(OBSOLETE(sys_utime)) /* used by libc4 */
  CALL(sys_ni_syscall)  /* was sys_stty */
  CALL(sys_ni_syscall)  /* was sys_getty */
  CALL(sys_access)
  CALL(sys_nice)
/* 35 */ CALL(sys_ni_syscall)  /* was sys_ftime */
  CALL(sys_sync)
  CALL(sys_kill)
  CALL(sys_rename)
  CALL(sys_mkdir)
/* 40 */ CALL(sys_rmdir)
  CALL(sys_dup)
  CALL(sys_pipe)
  CALL(sys_times)
  CALL(sys_ni_syscall)  /* was sys_prof */
/* 45 */ CALL(sys_brk)
  CALL(sys_setgid16)
  CALL(sys_getgid16)
  CALL(sys_ni_syscall)  /* was sys_signal */
  CALL(sys_geteuid16)
/* 50 */ CALL(sys_getegid16)
  CALL(sys_acct)
  CALL(sys_umount)
  CALL(sys_ni_syscall)  /* was sys_lock */
  CALL(sys_ioctl)
/* 55 */ CALL(sys_fcntl)
  .......

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/16439.html