• 系统调用流程梳理


    linux-3.5/arch/arm/include/asm/unistd.h
    #define __NR_OABI_SYSCALL_BASE  0x900000
    #define __NR_SYSCALL_BASE   __NR_OABI_SYSCALL_BASE
    //提供给应用层使用
    #define __NR_restart_syscall        (__NR_SYSCALL_BASE+  0)
    #define __NR_exit           (__NR_SYSCALL_BASE+  1)
    #define __NR_fork           (__NR_SYSCALL_BASE+  2)
    #define __NR_read           (__NR_SYSCALL_BASE+  3)
    #define __NR_write          (__NR_SYSCALL_BASE+  4)
    #define __NR_open           (__NR_SYSCALL_BASE+  5)
    #define __NR_close          (__NR_SYSCALL_BASE+  6)
                             ......
    #define __NR_setns          (__NR_SYSCALL_BASE+375)
    #define __NR_process_vm_readv       (__NR_SYSCALL_BASE+376)
    #define __NR_process_vm_writev      (__NR_SYSCALL_BASE+377)
     
    linux-3.5/arch/arm/kernel/entry-header.S
    scno    .req    r7      @ syscall number
    tbl .req    r8      @ syscall table pointer
    why .req    r8      @ Linux syscall (!= 0)
    tsk .req    r9      @ current thread_info
     
    linux-3.5/include/generated/asm-offsets.h
    #define S_R0 0 /* offsetof(struct pt_regs, ARM_r0)  @ */
    #define S_R1 4 /* offsetof(struct pt_regs, ARM_r1)  @ */
    #define S_R2 8 /* offsetof(struct pt_regs, ARM_r2)  @ */
    #define S_R3 12 /* offsetof(struct pt_regs, ARM_r3) @ */
    #define S_R4 16 /* offsetof(struct pt_regs, ARM_r4) @ */
    #define S_R5 20 /* offsetof(struct pt_regs, ARM_r5) @ */
    #define S_R6 24 /* offsetof(struct pt_regs, ARM_r6) @ */
    #define S_R7 28 /* offsetof(struct pt_regs, ARM_r7) @ */
    #define S_R8 32 /* offsetof(struct pt_regs, ARM_r8) @ */
    #define S_R9 36 /* offsetof(struct pt_regs, ARM_r9) @ */
    #define S_R10 40 /* offsetof(struct pt_regs, ARM_r10)   @ */
    #define S_FP 44 /* offsetof(struct pt_regs, ARM_fp) @ */
    #define S_IP 48 /* offsetof(struct pt_regs, ARM_ip) @ */
    #define S_SP 52 /* offsetof(struct pt_regs, ARM_sp) @ */
    #define S_LR 56 /* offsetof(struct pt_regs, ARM_lr) @ */
    #define S_PC 60 /* offsetof(struct pt_regs, ARM_pc) @ */
    #define S_PSR 64 /* offsetof(struct pt_regs, ARM_cpsr)  @ */
    #define S_OLD_R0 68 /* offsetof(struct pt_regs, ARM_ORIG_r0)    @ */
    #define S_FRAME_SIZE 72 /* sizeof(struct pt_regs)   @ */

    linux-3.5/arch/arm/include/asm/ptrace.h
    struct pt_regs {
        unsigned long uregs[18];

    #define ARM_cpsr    uregs[16]
    #define ARM_pc      uregs[15]
    #define ARM_lr      uregs[14]
    #define ARM_sp      uregs[13]
    #define ARM_ip      uregs[12]
    #define ARM_fp      uregs[11]
    #define ARM_r10     uregs[10]
    #define ARM_r9      uregs[9]
    #define ARM_r8      uregs[8]
    #define ARM_r7      uregs[7]
    #define ARM_r6      uregs[6]
    #define ARM_r5      uregs[5]
    #define ARM_r4      uregs[4]
    #define ARM_r3      uregs[3]
    #define ARM_r2      uregs[2]
    #define ARM_r1      uregs[1]
    #define ARM_r0      uregs[0]
    #define ARM_ORIG_r0 uregs[17]
     
    linux/arch/arm/kernel/calls.S
    /* 0 */     CALL(sys_restart_syscall)
            CALL(sys_exit)
            CALL(sys_fork_wrapper)
            CALL(sys_read)
            CALL(sys_write)
    /* 5 */     CALL(sys_open)

              ......
             
    /* 375 */   CALL(sys_setns)
            CALL(sys_process_vm_readv)
            CALL(sys_process_vm_writev)
    #ifndef syscalls_counted
    .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls     @第一次才会执行(NR_syscalls==1),syscalls_padding=3,保证以4对齐
    #define syscalls_counted
    #endif
    .rept syscalls_padding
            CALL(sys_ni_syscall)
    .endr
     
    linux-3.5/arch/arm/kernel/entry-common.S
    .equ NR_syscalls,0
    #define CALL(x) .equ NR_syscalls,NR_syscalls+1
    #include "calls.S"
    #undef CALL
    #define CALL(x) .long x
     
    /*
    * This is the syscall table declaration for native ABI syscalls.
    * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
    */
    #define ABI(native, compat) native
    #ifdef CONFIG_AEABI      
    #define OBSOLETE(syscall) sys_ni_syscall
    #else
    #define OBSOLETE(syscall) syscall
    #endif

    .type   sys_call_table, #object
    ENTRY(sys_call_table)    
    #include "calls.S"
    #undef ABI
    #undef OBSOLETE
     

        .align  5
    ENTRY(vector_swi)
    /****************************将中断发生前的寄存器状态备份入栈**********/
        sub sp, sp, #S_FRAME_SIZE          @在栈上开辟18*4的空间备份跳转之前的寄存器值
        stmia   sp, {r0 - r12}          @ Calling r0 - r12,备份r0 - r12寄存器
         ARM(   add r8, sp, #S_PC       )                                              
         ARM(   stmdb   r8, {sp, lr}^       )   @ Calling sp, lr
         mrs r8, spsr            @ called from non-FIQ mode, so ok. 将CPSR的值存在r8中  
         str lr, [sp, #S_PC]         @ Save calling PC                         
         str r8, [sp, #S_PSR]        @ Save CPSR                                    
         str r0, [sp, #S_OLD_R0]     @ Save OLD_R0 备份r0到栈空间中r17的位置(因为没有SPSR 所以这里多备份了一个r0,估计是为了标准化)                                 
         zero_fp                            @清空fp寄存器r11
        
        /*
         * Get the system call number.
         */

    #if defined(CONFIG_OABI_COMPAT)

        /*
         * If we have CONFIG_OABI_COMPAT then we need to look at the swi
         * value to determine if it is an EABI or an old ABI call.
         */
    #ifdef CONFIG_ARM_THUMB
        tst r8, #PSR_T_BIT
        movne   r10, #0             @ no thumb OABI emulation
        ldreq   r10, [lr, #-4]          @ get SWI instruction
    #else
        ldr r10, [lr, #-4]          @ get SWI instruction // get SWI instruction 利用lr取得swi指令的内容 
         //跳转前code段的内存{地址:内容:流水级},从下面的内存分布可以清楚看出lr - 4的含义 
        //{0x8:xxx:fetch<--pc},{0x4:xxx:decode<--lr},{0x0:swi num:exe}
    #endif
    #ifdef CONFIG_CPU_ENDIAN_BE8
        rev r10, r10            @ little endian instruction
    #endif

    #elif defined(CONFIG_AEABI)

        /*
         * Pure EABI user space always put syscall number into scno (r7).
         */
    #elif defined(CONFIG_ARM_THUMB)
        /* 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
    #endif

    /************为进入syscall具体函数做准备,主要是使调用符合ATPCS规范***********/
    #ifdef CONFIG_ALIGNMENT_TRAP
        ldr ip, __cr_alignment
        ldr ip, [ip]                    //? 
        mcr p15, 0, ip, c1, c0      @ update control registe 读ip中的数据到c1
    #endif
        enable_irq

        get_thread_info tsk
        adr tbl, sys_call_table     @ load syscall table pointer

    #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

        ldr r10, [tsk, #TI_FLAGS]       @ check for syscall tracing
        stmdb   sp!, {r4, r5}           @ push fifth and sixth args

    #ifdef CONFIG_SECCOMP
        tst r10, #_TIF_SECCOMP
        beq 1f
        mov r0, scno
        bl  __secure_computing
        add r0, sp, #S_R0 + S_OFF       @ pointer to regs
        ldmia   r0, {r0 - r3}           @ have to reload r0 - r3
    1:
    #endif

        tst r10, #_TIF_SYSCALL_WORK     @ 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 PC = *(tbl+(scno<<2))

        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

    ENDPROC(vector_swi) 
     
     
    系统调用的主流程:
         API->swi>sys_*->driver(sys_*)
     
    linux-3.5/fs/namei.c
    linux-3.5/fs/open.c    
    open()->SYSCALL_DEFINE3(open, ...)->do_sys_open()->do_filp_open()->
    path_openat()->do_last()->nameidata_to_filp()->do_dentry_open()->open(inode, f)
     
    1.获取系统调用号(ldr r10, [lr, #-4]);
    2.根据tbl+scno来调用指定的系统调用接口。
  • 相关阅读:
    【LeetCode】152. 乘积最大子数组(DP)
    【剑指Offer】49. 丑数(三指针)
    [P1979][NOIP2013] 华容道 (BFS建图+SPFA)
    [P1850][NOIP2016] 换教室 (期望+DP+Floyd)
    差分约束学习笔记
    [P1291][SHOI2002] 百事世界杯之旅 (期望)
    [P4342][IOI1998] Polygon (区间DP)
    [P3802] 小魔女帕琪 (期望)
    [P1273] 有线电视网 (树形DP+分组背包)
    树链剖分学习
  • 原文地址:https://www.cnblogs.com/black-mamba/p/5043963.html
Copyright © 2020-2023  润新知