您现在的位置是:主页 > news > 宁波seo优化外包公司/网店seo是什么意思

宁波seo优化外包公司/网店seo是什么意思

admin2025/4/19 22:36:39news

简介宁波seo优化外包公司,网店seo是什么意思,大淘客官网做的网站打不开,百度网站上做推广受骗本文以ARM64为例,介绍如何添加系统调用,首先来介绍一些代码执行流程: 首先来看异常向量表的配置,内核在arch/arm64/kernel/entry.S汇编代码中设置了异常向量表。 /** Exception vectors.*/.pushsection ".entry.text"…

宁波seo优化外包公司,网店seo是什么意思,大淘客官网做的网站打不开,百度网站上做推广受骗本文以ARM64为例,介绍如何添加系统调用,首先来介绍一些代码执行流程: 首先来看异常向量表的配置,内核在arch/arm64/kernel/entry.S汇编代码中设置了异常向量表。 /** Exception vectors.*/.pushsection ".entry.text"…

本文以ARM64为例,介绍如何添加系统调用,首先来介绍一些代码执行流程:

首先来看异常向量表的配置,内核在arch/arm64/kernel/entry.S汇编代码中设置了异常向量表。

/** Exception vectors.*/.pushsection ".entry.text", "ax".align  11
ENTRY(vectors)kernel_ventry   1, sync_invalid         // Synchronous EL1tkernel_ventry   1, irq_invalid          // IRQ EL1tkernel_ventry   1, fiq_invalid          // FIQ EL1tkernel_ventry   1, error_invalid        // Error EL1tkernel_ventry   1, sync             // Synchronous EL1hkernel_ventry   1, irq              // IRQ EL1hkernel_ventry   1, fiq_invalid          // FIQ EL1hkernel_ventry   1, error_invalid        // Error EL1hkernel_ventry   0, sync             // Synchronous 64-bit EL0kernel_ventry   0, irq              // IRQ 64-bit EL0kernel_ventry   0, fiq_invalid          // FIQ 64-bit EL0kernel_ventry   0, error_invalid        // Error 64-bit EL0#ifdef CONFIG_COMPATkernel_ventry   0, sync_compat, 32      // Synchronous 32-bit EL0kernel_ventry   0, irq_compat, 32       // IRQ 32-bit EL0kernel_ventry   0, fiq_invalid_compat, 32   // FIQ 32-bit EL0kernel_ventry   0, error_invalid_compat, 32 // Error 32-bit EL0
#elsekernel_ventry   0, sync_invalid, 32     // Synchronous 32-bit EL0kernel_ventry   0, irq_invalid, 32      // IRQ 32-bit EL0kernel_ventry   0, fiq_invalid, 32      // FIQ 32-bit EL0kernel_ventry   0, error_invalid, 32        // Error 32-bit EL0
#endif
END(vectors)

上面的代码进一步展开,即使就是设置不同mode下的异常向量表,异常可以分为4组,每组异常有4个,所以这里一共会设置16个entry。4组异常分别对应4种情况下发生异常时的处理。上面的4组,按照顺序分别对应如下4中情况:

(1)运行级别不发生切换,从ELx变化到ELx,使用SP_EL0,这种情况在Linux kernel都是不处理的,使用invalid entry。

(2)运行级别不发生切换,从ELx变化到ELx,使用SP_ELx。这种情况下在Linux中比较常见。

(3)异常需要进行级别切换来进行处理,并且使用aarch64模式处理,比如64位用户态程序发生系统调用,CPU会从EL0切换到EL1,并且使用aarch64模式处理异常。

(4)异常需要进行级别切换来进行处理,并且使用aarch32模式处理。比如32位用户态程序发生系统调用,CPU会从EL0切换到EL1,并且使用aarch32模式进行处理。

前面设置了异常向量表,我们来进一步查看SVC mode的处理。当系统调用时CPU会切换到SVC mode,并跳转到对应的地址去运行。

kernel中会配置两个SVC Handler,分别对应这SVC_32/SVC_64两种mode,32bit程序和64bit程序执行系统调用会跳转到两个不同的handler去执行。

内核在arch/arm64/kernel/entry.S汇编代码中设置了SVC异常entry。

64-bit运行模式解析

如下函数设置了64-bit状态下的异常向量表设置,其中红色部分是svc handler配置:

arch/arm64/kernel/entry.S:.align  6
el0_sync:kernel_entry 0mrs x25, esr_el1            // read the syndrome registerlsr x24, x25, #ESR_ELx_EC_SHIFT // exception classcmp x24, #ESR_ELx_EC_SVC64      // SVC in 64-bit stateb.eq    el0_svccmp x24, #ESR_ELx_EC_DABT_LOW   // data abort in EL0b.eq    el0_dacmp x24, #ESR_ELx_EC_IABT_LOW   // instruction abort in EL0b.eq    el0_iacmp x24, #ESR_ELx_EC_FP_ASIMD   // FP/ASIMD accessb.eq    el0_fpsimd_acccmp x24, #ESR_ELx_EC_FP_EXC64   // FP/ASIMD exceptionb.eq    el0_fpsimd_exccmp x24, #ESR_ELx_EC_SYS64      // configurable trapb.eq    el0_syscmp x24, #ESR_ELx_EC_SP_ALIGN   // stack alignment exceptionb.eq    el0_sp_pccmp x24, #ESR_ELx_EC_PC_ALIGN   // pc alignment exceptionb.eq    el0_sp_pccmp x24, #ESR_ELx_EC_UNKNOWN    // unknown exception in EL0b.eq    el0_undefcmp x24, #ESR_ELx_EC_BREAKPT_LOW    // debug exception in EL0b.ge    el0_dbgb   el0_inv

el0_svc的实现如下:

/** SVC handler.*/.align  6
el0_svc:adrp    stbl, sys_call_table        // load syscall table pointeruxtw    scno, w8            // syscall number in w8mov sc_nr, #__NR_syscalls
el0_svc_naked:                  // compat entry pointstp x0, scno, [sp, #S_ORIG_X0]  // save the original x0 and syscall numberenable_dbg_and_irqct_user_exit 1ldr x16, [tsk, #TSK_TI_FLAGS]   // check for syscall hookstst x16, #_TIF_SYSCALL_WORKb.ne    __sys_tracecmp     scno, sc_nr                     // check upper syscall limitb.hs    ni_sysldr x16, [stbl, scno, lsl #3]   // address in the syscall tableblr x16             // call sys_* routineb   ret_fast_syscall
ni_sys:mov x0, spbl  do_ni_syscallb   ret_fast_syscall
ENDPROC(el0_svc)

可以看到它会去查找sys_call_table这个数组并找到对应的系统调用函数去执行,注意其中有一个关键函数do_ni_syscall,(no implement syscall),当系统调用遇到一些限制或者问题时会跳转到该函数去执行。

sys_call_table的定义在如下文件中:

arch/arm64/kernel/sys.c:
/** The sys_call_table array must be 4K aligned to be accessible from* kernel/entry.S.*/
void * const sys_call_table[__NR_syscalls] __aligned(4096) = {[0 ... __NR_syscalls - 1] = sys_ni_syscall,
#include <asm/unistd.h>
};

这个数组在创建时首先会把所有的数组成员设置为sys_ni_syscall,而后根据asm/unistd.h中的内容做进一步初始化。其实最终该头文件会把include/uapi/asm-generic//unistd.h包含进来,也就是这个头文件会是最终定义数组的地方。

......
__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
#define __NR_ustat 1070
__SYSCALL(__NR_ustat, sys_ustat)
#define __NR_vfork 1071
__SYSCALL(__NR_vfork, sys_vfork)
#define __NR_oldwait4 1072
__SYSCALL(__NR_oldwait4, sys_wait4)
#define __NR_recv 1073
__SYSCALL(__NR_recv, sys_recv)
#define __NR_send 1074
__SYSCALL(__NR_send, sys_send)
#define __NR_bdflush 1075
__SYSCALL(__NR_bdflush, sys_bdflush)
#define __NR_umount 1076
__SYSCALL(__NR_umount, sys_oldumount)
#define __ARCH_WANT_SYS_OLDUMOUNT
#define __NR_uselib 1077
__SYSCALL(__NR_uselib, sys_uselib)
#define __NR__sysctl 1078
__SYSCALL(__NR__sysctl, sys_sysctl)
#define __NR_fork 1079
#ifdef CONFIG_MMU
__SYSCALL(__NR_fork, sys_fork)
#else
__SYSCALL(__NR_fork, sys_ni_syscall)
#endif /* CONFIG_MMU */
......

32-bit运行模式解析

如下函数设置了32-bit状态下的异常向量表设置,其中红色部分是svc handler配置:

arch/arm64/kernel/entry.S#ifdef CONFIG_COMPAT.align  6el0_sync_compat:kernel_entry 0, 32mrs x25, esr_el1            // read the syndrome registerlsr x24, x25, #ESR_ELx_EC_SHIFT // exception classcmp x24, #ESR_ELx_EC_SVC32      // SVC in 32-bit stateb.eq    el0_svc_compatcmp x24, #ESR_ELx_EC_DABT_LOW   // data abort in EL0b.eq    el0_dacmp x24, #ESR_ELx_EC_IABT_LOW   // instruction abort in EL0b.eq    el0_iacmp x24, #ESR_ELx_EC_FP_ASIMD   // FP/ASIMD accessb.eq    el0_fpsimd_acccmp x24, #ESR_ELx_EC_FP_EXC32   // FP/ASIMD exceptionb.eq    el0_fpsimd_exccmp x24, #ESR_ELx_EC_PC_ALIGN   // pc alignment exceptionb.eq    el0_sp_pccmp x24, #ESR_ELx_EC_UNKNOWN    // unknown exception in EL0b.eq    el0_undefcmp x24, #ESR_ELx_EC_CP15_32    // CP15 MRC/MCR trapb.eq    el0_undefcmp x24, #ESR_ELx_EC_CP15_64    // CP15 MRRC/MCRR trapb.eq    el0_undefcmp x24, #ESR_ELx_EC_CP14_MR    // CP14 MRC/MCR trapb.eq    el0_undefcmp x24, #ESR_ELx_EC_CP14_LS    // CP14 LDC/STC trapb.eq    el0_undefcmp x24, #ESR_ELx_EC_CP14_64    // CP14 MRRC/MCRR trapb.eq    el0_undefcmp x24, #ESR_ELx_EC_BREAKPT_LOW    // debug exception in EL0b.ge    el0_dbgb   el0_invel0_svc_compat:/** AArch32 syscall handling*/adrp    stbl, compat_sys_call_table // load compat syscall table pointeruxtw    scno, w7            // syscall number in w7 (r7)mov     sc_nr, #__NR_compat_syscallsb   el0_svc_naked.align  6el0_irq_compat:kernel_entry 0, 32b   el0_irq_naked#endif

el0_svc_compat的实现如下:

el0_svc_compat:/** AArch32 syscall handling*/adrp    stbl, compat_sys_call_table // load compat syscall table pointeruxtw    scno, w7            // syscall number in w7 (r7)mov     sc_nr, #__NR_compat_syscallsb   el0_svc_naked.align  6
el0_irq_compat:kernel_entry 0, 32b   el0_irq_naked

可以看到它会去查找compat_sys_call_table这个数组并找到对应的系统调用函数去执行,compat_sys_call_table的定义在如下文件中:

arch/arm64/kernel/sys32.c:/** The sys_call_table array must be 4K aligned to be accessible from* kernel/entry.S.*/void * const compat_sys_call_table[__NR_compat_syscalls] __aligned(4096) = {[0 ... __NR_compat_syscalls - 1] = sys_ni_syscall,#include <asm/unistd32.h>};

这个数组在创建时首先会把所有的数组成员设置为sys_ni_syscall,而后根据asm/unistd32.h中的内容做进一步初始化。其实最终该头文件会把arch/arm64/include/asm/unistd32.h包含进来,也就是这个头文件会是最终定义函数数组的地方。

arch/arm64/include/asm/unistd32.h:
......__SYSCALL(__NR_process_vm_writev, compat_sys_process_vm_writev)#define __NR_kcmp 378__SYSCALL(__NR_kcmp, sys_kcmp)#define __NR_finit_module 379__SYSCALL(__NR_finit_module, sys_finit_module)#define __NR_sched_setattr 380__SYSCALL(__NR_sched_setattr, sys_sched_setattr)#define __NR_sched_getattr 381__SYSCALL(__NR_sched_getattr, sys_sched_getattr)#define __NR_renameat2 382__SYSCALL(__NR_renameat2, sys_renameat2)#define __NR_seccomp 383__SYSCALL(__NR_seccomp, sys_seccomp)#define __NR_getrandom 384__SYSCALL(__NR_getrandom, sys_getrandom)#define __NR_memfd_create 385__SYSCALL(__NR_memfd_create, sys_memfd_create)#define __NR_bpf 386__SYSCALL(__NR_bpf, sys_bpf)#define __NR_execveat 387__SYSCALL(__NR_execveat, compat_sys_execveat)#define __NR_userfaultfd 388__SYSCALL(__NR_userfaultfd, sys_userfaultfd)#define __NR_membarrier 389__SYSCALL(__NR_membarrier, sys_membarrier)#define __NR_mlock2 390__SYSCALL(__NR_mlock2, sys_mlock2)#define __NR_copy_file_range 391__SYSCALL(__NR_copy_file_range, sys_copy_file_range)#define __NR_preadv2 392__SYSCALL(__NR_preadv2, compat_sys_preadv2)#define __NR_pwritev2 393__SYSCALL(__NR_pwritev2, compat_sys_pwritev2)
......

最后来看一下do_ni_syscall,内核中没有意义的系统调用号都会执行到该函数上面:

asmlinkage long do_ni_syscall(struct pt_regs *regs)
{
#ifdef CONFIG_COMPATlong ret;if (is_compat_task()) {ret = compat_arm_syscall(regs);if (ret != -ENOSYS)return ret;}
#endifif (show_unhandled_signals_ratelimited()) {pr_info("%s[%d]: syscall %d\n", current->commtask_pid_nr(current), (int)regs->syscallno);dump_instr("", regs);if (user_mode(regs))     __show_regs(regs);} return sys_ni_syscall();
}

本文基于kernel-4.9版本,原创文章,转载请标注。