linux系统调用过程分析

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);

借用一下别人的图:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值