linux下系统调用的过程

系统调用:

系统调用是内核的入口 ,借助这一机制,进程可以请求内核以自己的名义去执行某些动作。以应用程序编程接口(API)的形式,内核提供一系列API供应用程序调用

在深入系统调用的运作方式之前需得理解下面几点:

  • 系统调用将处理器从用户状态切换到内核状态,以便cpu访问受到保护的系统内核
  • 系统调用的组成是固定的,每个系统调用都有一个唯一的数字标识符,程序通过名称来标识系统调用
  • 每个系统调用可以辅之以一套参数,对用户空间(亦即进程的虚拟内存空间)与内核空间之间传递信息加以规范

从编程的角度讲,系统调用和调用c语言的函数很像,然而,在执行系统调用时,会比c语言的函数调用复杂很多,下面是系统调用的详细过程:

  1. 应用程序通过调用c语言函数库中的外壳函数(wrapper)来发起系统调用。
  2. 对系统调用中断来处理例程来讲,外壳函数必须保证所有的系统调用的参数可用。通过堆栈这些参数传入外壳函数后,外壳函数会将这些参数复制到寄存器。
  3. 所有系统调用进入内核的方式都相同,所以内核需要区分每个系统调用,为此,外壳函数会把系统调用的编号复制到一个特殊的cpu(%eax)
  4. 外壳函数调用系统中断指令(int 0x80),引发处理器从用户态切换到内核态,并执行系统中断的中断矢量所指向的代码。

较新的x86_32硬件平台实现了sysenter指令,比传统的int 0x80进入内核的速度更快,2.6内核和glibc2.3.2以后的版本都支持sysenter指令

  1. 为了响应中断0x80,内核会调用system_call()例程,来处理这次中断。

1、 在内核栈中保存寄存器的值 在内核栈中保存寄存器的值
2、审核系统调用编号的有效性。
3、以系统调用编号对存放所有调用服务例程的列表(内核变量sys_call_table)进行索引,发现并调用相应编号的系统例程。若系统调用例程带有参数,那么首先检查参数的有效性,例如,会检查地址指向用户空间的内存的位置是否有效。随后该服务例程会执行必要的任务,这可能涉及对特定参数中指定地址处的值的修改,以及在用户内存和内核内存中传递数据,最后,该服务例程会将结果返回给system_call()例程。

  1. 若系统调用例程的返回值表明调用有误,外壳函数会将该值用来设置全局变量errno,然后外壳函数会返回到调用函数,并同时返回一个整数0或者-1,0表示成功,-1表示失败。通过查看全局变量erron来获取错误信息。

下面是exec函数的系统调用的流程图:

在这里插入图片描述

欢迎关注问我团队公众号:

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值