加入收藏 | 设为首页 | 会员中心 | 我要投稿 温州站长网 (https://www.0577zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux系统调用过程

发布时间:2021-02-22 23:14:42 所属栏目:Linux 来源:网络整理
导读:副标题#e# 1 ? fork、open、write 等等函数实际上并不是真正的系统调用函数,他们都只是c库, swi 指令,产生一个软中断,使CPU 陷入内核态, 2 系统调用过程 http://www.linuxidc.com/Linux/2015-04/116546.htm 系统调用是操作系统提供给用户(应用程序)
副标题[/!--empirenews.page--]

1

?

Linux系统调用过程

fork、open、write 等等函数实际上并不是真正的系统调用函数,他们都只是c库, swi 指令,产生一个软中断,使CPU 陷入内核态,

2 系统调用过程

http://www.linuxidc.com/Linux/2015-04/116546.htm

系统调用是操作系统提供给用户(应用程序)的一组接口,每个系统调用都有一个对应的系统调用函数来完成相应的工作。用户通过这个接口向操作系统申请服务,如访问硬件,管理进程等等。但是因为用户程序运行在用户空间,而系统调用运行在内核空间,因此用户程序不能直接调用系统调用函数,我们经常看到的比如fork、open、write 等等函数实际上并不是真正的系统调用函数,他们都只是c库,在这些函数里将执行一个软中断 swi 指令,产生一个软中断,使CPU 陷入内核态,接着在内核中进行一系列的判断,判断出是哪个系统调用,再转到真正的系统调用函数,完成相应的功能。下面举一个简单的例子说明从用户态调用一个“系统调用”,到内核处理的整个执行流程。

  用户态程序如下:

? ? ? void pk()

  {

    __asm__(

    "ldr? r7? =365 n"

    "swi n"

    :

    :

    :

    );

  }

  int main()

  {

   ? ?pk();

    retrun 0;

  }

  上面的代码中,我自己实现了一个新的系统调用,具体怎么做,后面再具体描述。pk()事实上就可以类比于平时我们在用户程序里调用的 open() 等函数,这个函数只做了一件简单的事:将系统调用号传给 r7 ,,然后产生一软中断。接着CPU陷入内核

  内核态:

  CPU相应这个软中断以后,PC指针会到相应的中断向量表中取指,中断向量表在内核代码中:arch/arm/kernel/entry-armv.S? 中定义

.LCvswi:

?.globl?__stubs_end__stubs_end:

?.equ?stubs_offset,__vectors_start + 0x200 - __stubs_start

?.globl?__vectors_start__vectors_start:?ARM(?swi?SYS_ERROR0?)?THUMB(?svc?#0? )?THUMB(?nop? ?)?W(b)?vector_und + stubs_offset?W(b)?vector_pabt + stubs_offset?W(b)?vector_dabt + stubs_offset?W(b)?vector_addrexcptn + stubs_offset?W(b)?vector_irq + stubs_offset?W(b)?vector_fiq + stubs_offset

?.globl?__vectors_end__vectors_end:

当pc取到如上的指令后,会跳到 vector_swi 这个标号,这个标号在arch/arm/kernel/entry-commen.S 中定义。

?.align?5?sub?sp,sp,#S_FRAME_SIZE?stmia?sp,{r0 - r12}? ?@ Calling r0 - r12?ARM(?add?r8,#S_PC? )?ARM(?stmdb?r8,{sp,lr}^? )?@ Calling sp,lr?THUMB(?mov?r8,sp? ?)?THUMB(?store_user_sp_lr r8,r10,S_SP?)?@ calling sp,lr?mrs?r8,spsr? ?@ called from non-FIQ mode,so ok.?str?lr,[sp,#S_PC]? ?@ Save calling PC?str?r8,#S_PSR]? @ Save CPSR?str?r0,#S_OLD_R0]? @ Save OLD_R0?zero_fp

?/*? * ? */

#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,#-4]? ?@ get SWI instruction? A710(?and?ip,#0x0f000000? @ check for SWI? )? A710(?teq?ip,#0x0f000000? ? ? )? A710(?bne?.Larm710bug? ? ? )#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).? */? A710(?ldr?ip,#-4]? ?@ get SWI instruction?)? A710(?and?ip,ip,#0x0f000000? ? ? )? A710(?bne?.Larm710bug? ? ? )

#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,#-4]

#else

?/* Legacy ABI only. */?ldr?scno,scno,#0x0f000000? ? ? )? A710(?bne?.Larm710bug? ? ? )

#endif

#ifdef CONFIG_ALIGNMENT_TRAP?ldr?ip,__cr_alignment?ldr?ip,[ip]?mcr?p15,c1,c0? @ update control register#endif?enable_irq

?get_thread_info tsk

??ldr?ip,[tsk,#TI_FLAGS]? @ check for syscall tracing

#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,#0xff000000?eorne?scno,#__NR_OABI_SYSCALL_BASE?ldrne?tbl,=sys_oabi_call_table#elif !defined(CONFIG_AEABI)?bic?scno,#0xff000000? @ mask off SWI op-code?eor?scno,#__NR_SYSCALL_BASE?@ check OS number#endif

?stmdb?sp!,{r4,r5}? ?@ push fifth and sixth args?tst?ip,#_TIF_SYSCALL_TRACE? @ are we tracing syscalls??bne?__sys_trace

?cmp?scno,#NR_syscalls? @ check upper syscall limit?adr?lr,BSYM(ret_fast_syscall)?@ return address?

?add?r1,#S_OFF2:?mov?why,#0? ? @ no longer a real syscall?cmp?scno,#(__ARM_NR_BASE - __NR_SYSCALL_BASE)?eor?r0,#__NR_SYSCALL_BASE?@ put OS number back?bcs?arm_syscall??b?sys_ni_syscall? ?@ not private func

从上面可以看出,当CPU从中断向量表转到vector_swi 之后,完成了几件事情:

系统调用表定义在:arch/arm/kernel/Calls.S

* This program is free software; you can redistribute it and/or modify?* it under the terms of the GNU General Public License version 2 as?* published by the Free Software Foundation.?*?*? This file is included thrice in entry-common.S?*//* 0 */? CALL(sys_restart_syscall)? CALL(sys_exit)? CALL(sys_fork_wrapper)? CALL(sys_read)? CALL(sys_write)/* 5 */? CALL(sys_open)? CALL(sys_close)? CALL(sys_ni_syscall)? /* was sys_waitpid */? CALL(sys_creat)? CALL(sys_link)/* 10 */?CALL(sys_unlink)? CALL(sys_execve_wrapper)? CALL(sys_chdir)? CALL(OBSOLETE(sys_time))?/* used by libc4 */? CALL(sys_mknod)/* 15 */?CALL(sys_chmod)? CALL(sys_lchown16)? CALL(sys_ni_syscall)? /* was sys_break */? CALL(sys_ni_syscall)? /* was sys_stat */? CALL(sys_lseek)/* 20 */?CALL(sys_getpid)? CALL(sys_mount)? CALL(OBSOLETE(sys_oldumount))?/* used by libc4 */? CALL(sys_setuid16)? CALL(sys_getuid16)/* 25 */?CALL(OBSOLETE(sys_stime))? CALL(sys_ptrace)? CALL(OBSOLETE(sys_alarm))?/* used by libc4 */? CALL(sys_ni_syscall)? /* was sys_fstat */? CALL(sys_pause)/* 30 */?CALL(OBSOLETE(sys_utime))?/* used by libc4 */? CALL(sys_ni_syscall)? /* was sys_stty */? CALL(sys_ni_syscall)? /* was sys_getty */? CALL(sys_access)? CALL(sys_nice)/* 35 */?CALL(sys_ni_syscall)? /* was sys_ftime */? CALL(sys_sync)? CALL(sys_kill)? CALL(sys_rename)? CALL(sys_mkdir)/* 40 */?CALL(sys_rmdir)? CALL(sys_dup)? CALL(sys_pipe)? CALL(sys_times)? CALL(sys_ni_syscall)? /* was sys_prof *//* 45 */?CALL(sys_brk)? CALL(sys_setgid16)? CALL(sys_getgid16)? CALL(sys_ni_syscall)? /* was sys_signal */? CALL(sys_geteuid16)/* 50 */?CALL(sys_getegid16)? CALL(sys_acct)? CALL(sys_umount)? CALL(sys_ni_syscall)? /* was sys_lock */? CALL(sys_ioctl)/* 55 */?CALL(sys_fcntl)  .......

(编辑:温州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读