1、ARM系统应用调用open的过程:
open -> glibc -> swi 0x0 -> kernel -> vector_swi -> sys_openat (SYSCALL_DEFINE4(openat, xxx))
1)glibc端:
-> open(xxx) // fcntl.h
-> T_PSEUDO (sys_open, __libc_open, 3) // sysdeps/unix/syscall-template.S
-> DO_CALL (__libc_open, 3) // sysdeps/unix/sysv/linux/arm/sysdep.h
-> swi 0x0; // swi软中断
注:open系统调用是通过glibc的脚本进行封装的,封装过程如下:
编译时通过make-syscall.sh脚本读取syscall.list中的内容参考
syscall-template.S模板对相关系统调用进行封装;
sysdeps/unix/syscall.list相关内容:
# File name Caller Syscall name Args Strong name Weak names
open - open Ci:siv __libc_open __open open
sysdeps/unix/make-syscall.sh
-> sysdeps/unix/syscall.list
-> sysdeps/unix/syscall-template.S
-> T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
-> PSEUDO (SYMBOL, NAME, N)
-> ENTRY (name)
-> DO_CALL (syscall_name, args);
-> swi 0x0;
2)kernel端:
// 注册中断向量处理函数
Low-level vector interface routines
.word vector_swi // arch/arm/kernel/entry-armv.S
// 系统调用函数地址表
ENTRY(sys_call_table) // arch/arm/kernel/entry-common.S
#include "calls.S"
// swi中断处理
-> ENTRY(vector_swi) // arch/arm/kernel/entry-common.S
-> sys_call_table[] // 根据相应的系统调用号查找到对应的系统调用函数地址
-> sys_openat // fs/open.c
-> SYSCALL_DEFINE4(openat, xxx)
2、X86_32系统应用调用open的过程:
open -> glibc -> int $0x80 -> kernel -> entry_INT80_32 -> compat_sys_openat (COMPAT_SYSCALL_DEFINE4(openat, xxx))
1)glibc端:
-> open(xxx) // fcntl.h
-> T_PSEUDO (sys_open, __libc_open, 3) // sysdeps/unix/syscall-template.S
-> DO_CALL (__libc_open, 3) // sysdeps/unix/sysv/linux/i386/sysdep.h
-> ENTER_KERNEL
-> int $0x80 // int80中断
注:open系统调用是通过glibc的脚本进行封装的,封装过程如下:
编译时通过make-syscall.sh脚本读取syscall.list中的内容参考
syscall-template.S模板对相关系统调用进行封装;
sysdeps/unix/syscall.list相关内容:
# File name Caller Syscall name Args Strong name Weak names
open - open Ci:siv __libc_open __open open
sysdeps/unix/make-syscall.sh
-> sysdeps/unix/syscall.list
-> sysdeps/unix/syscall-template.S
-> T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
-> PSEUDO (SYMBOL, NAME, N)
-> ENTRY (name)
-> DO_CALL (syscall_name, args);
-> ENTER_KERNEL
-> int $0x80
2)kernel端:
// 注册中断向量处理函数
start_kernel // init/main.c
-> trap_init() // arch/x86/kernel/traps.c
-> set_system_intr_gate(IA32_SYSCALL_VECTOR, entry_INT80_32);
-> set_bit(IA32_SYSCALL_VECTOR, used_vectors);
// 系统调用函数地址表
syscall_32.tbl -> ia32_sys_call_table[__NR_syscall_compat_max+1] // arch/x86/entry/syscall_32.c
// int80中断处理
ENTRY(entry_INT80_32) // arch/x86/entry/entry_32.S
-> do_int80_syscall_32 // arch/x86/entry/common.c
-> do_syscall_32_irqs_on
-> regs->ax = ia32_sys_call_table[nr](args)
-> compat_sys_openat // fs/compat.c
-> COMPAT_SYSCALL_DEFINE4(openat, xxx)
3、X86_64系统应用调用open的过程:
open -> glibc -> int $0x80 -> kernel -> entry_SYSCALL_64 -> sys_openat (SYSCALL_DEFINE3(openat, xxx))
1)glibc端:
-> open(xxx) // fcntl.h
-> T_PSEUDO (sys_open, __libc_open, 3) // sysdeps/unix/syscall-template.S
-> DO_CALL (__libc_open, 3) // sysdeps/unix/sysv/linux/x86_64/sysdep.h
-> syscall; // syscall指令
注:open系统调用是通过glibc的脚本进行封装的,封装过程如下:
编译时通过make-syscall.sh脚本读取syscall.list中的内容参考
syscall-template.S模板对相关系统调用进行封装;
sysdeps/unix/syscall.list相关内容:
# File name Caller Syscall name Args Strong name Weak names
open - open Ci:siv __libc_open __open open
sysdeps/unix/make-syscall.sh
-> sysdeps/unix/syscall.list
-> sysdeps/unix/syscall-template.S
-> T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
-> PSEUDO (SYMBOL, NAME, N)
-> ENTRY (name)
-> DO_CALL (syscall_name, args);
-> syscall;
2)kernel端:
// 注册中断向量处理函数
start_kernel // init/main.c
-> trap_init() // arch/x86/kernel/traps.c
-> cpu_init() // arch/x86/kernel/cpu/common.c
-> syscall_init()
-> wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
// 系统调用函数地址表
syscall_64.tbl -> sys_call_table[__NR_syscall_max+1] // arch/x86/entry/syscall_64.c
// syscall指令处理
ENTRY(entry_SYSCALL_64) // arch/x86/entry/entry_64.S
-> do_syscall_64 // arch/x86/entry/common.c
-> regs->ax = sys_call_table[nr & __SYSCALL_MASK](args)
-> sys_openat // fs/open.c
-> SYSCALL_DEFINE3(openat, xxx)
4、未涉及内容:
1)模式切换(用户模式,内核模式);
2)参数传递和返回(系统调用号,函数参数,返回值);
3)系统调用前的准备(sysenter/syscall)和调用后的收尾(sysexit/sysret)工作;
4)不通过glibc的系统调用,即直接与内核发生的系统调用(如sys_init_module);
借用一下别人的图: