赞
踩
在用户空间和内核空间之间,通过Syscall(系统调用, system call)的中间层来通信,连接用户态和内核态的桥梁。在ARM架构中,用户态程序通过swi 软中断进入内核态执行对应的系统调用,对于每一个系统调用都有对应的系统调用号,定义在unistd.h中。通过系统调用的方式,在一定程度上保护了系统的安全。
binonic
bionic/libc/kernel/uapi/asm-generic/unistd.h
bionic/libc/kernel/uapi/asm-arm64/asm/unistd.h
bionic/libc/arch-arm64/bionic/syscall.S
out/soong/.intermediates/bionic/libc/syscalls-arm.S
kernel
arch/arm64/include/asm/unistd32.h
arch/arm64/kernel/entry.S:947: bl el0_svc_compat_handler
arch/arm64/kernel/syscall.c:167:asmlinkage void el0_svc_compat_handler(struct pt_regs *regs)
unistd32.h (arch/arm64/include/asm/unistd32.h)
#define __NR_restart_syscall 0
__SYSCALL(__NR_restart_syscall, sys_restart_syscall)
#define __NR_exit 1
__SYSCALL(__NR_exit, sys_exit)
#define __NR_fork 2
__SYSCALL(__NR_fork, sys_fork)
#define __NR_read 3
__SYSCALL(__NR_read, sys_read)
#define __NR_write 4
__SYSCALL(__NR_write, sys_write)
#define __NR_open 5
__SYSCALL(__NR_open, compat_sys_open)
#define __NR_close 6
__SYSCALL(__NR_close, sys_close)
生成路径: out/soong/.intermediates/bionic/libc/syscalls-arm.S
genrule {
name: "syscalls-arm64.S",
out: ["syscalls-arm64.S"],
srcs: ["SYSCALLS.TXT"],
tool_files: [":bionic-gensyscalls"],
cmd: "$(location :bionic-gensyscalls) arm64 $(in) > $(out)",
}
用户态程序通过read,write等系统调用,最终跑到syscalls-arm.S中,通过swi 软中断进入内核态,最终调用到内核entry.S所对应的函数为el0_svc_compat函数,一些汇编相关的指令不懂。
ENTRY(read) mov ip, r7 .cfi_register r7, ip ldr r7, =__NR_read swi #0 mov r7, ip .cfi_restore r7 cmn r0, #(MAX_ERRNO + 1) bxls lr neg r0, r0 b __set_errno_internal END(read) ENTRY(write) mov ip, r7 .cfi_register r7, ip ldr r7, =__NR_write swi #0 mov r7, ip .cfi_restore r7 cmn r0, #(MAX_ERRNO + 1) bxls lr neg r0, r0 b __set_errno_internal END(write)
通过bl指令跳转到el0_svc_compat_handler函数,接下来是C语言的流程
el0_svc_compat:
gic_prio_kentry_setup tmp=x1
mov x0, sp
bl el0_svc_compat_handler
b ret_to_user
el0_svc_common函数中间没有复杂逻辑,将寄存器参数和syscall_table传给了invoke_syscall函数,invoke_syscall中判断对应的系统号在syscall_table中是否存在,如果存在则调用对应的sys_xx函数,比如SYSCALL(__NR_exit, sys_exit),不存在则返回错误吗
static long __invoke_syscall(struct pt_regs *regs, syscall_fn_t syscall_fn) { return syscall_fn(regs); } static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, const syscall_fn_t syscall_table[]) { invoke_syscall(regs, scno, sc_nr, syscall_table); } static void invoke_syscall(struct pt_regs *regs, unsigned int scno, unsigned int sc_nr, const syscall_fn_t syscall_table[]) { long ret; if (scno < sc_nr) { syscall_fn_t syscall_fn; syscall_fn = syscall_table[array_index_nospec(scno, sc_nr)]; ret = __invoke_syscall(regs, syscall_fn); } else { ret = do_ni_syscall(regs, scno); } if (is_compat_task()) ret = lower_32_bits(ret); regs->regs[0] = ret; } #ifdef CONFIG_COMPAT asmlinkage void el0_svc_compat_handler(struct pt_regs *regs) { el0_svc_common(regs, regs->regs[7], __NR_compat_syscalls, compat_sys_call_table); } #endif const syscall_fn_t compat_sys_call_table[__NR_compat_syscalls] = { [0 ... __NR_compat_syscalls - 1] = __arm64_sys_ni_syscall, #include <asm/unistd32.h> };
#define __NR_restart_syscall 0
__SYSCALL(__NR_restart_syscall, sys_restart_syscall)
#define __NR_exit 1
__SYSCALL(__NR_exit, sys_exit)
#define __NR_fork 2
__SYSCALL(__NR_fork, sys_fork)
#define __NR_read 3
__SYSCALL(__NR_read, sys_read)
#define __NR_write 4
__SYSCALL(__NR_write, sys_write)
#define __NR_open 5
__SYSCALL(__NR_open, compat_sys_open)
#define __NR_close 6
__SYSCALL(__NR_close, sys_close)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。