linux系统调用

1. 以c标准库为例分析系统调用的实现

关于 什么是系统调用 本文不过多赘述

  • syscall() 是一个较为底层的接口,允许程序通过系统调用号直接调用内核服务,函数原型如下:
    #include <sys/syscall.h>
    /*
     * number;系统调用号
     * ...: 根据具体系统调用传递参数(最多 6 个)
     */
    long syscall(long number, ...);
    
  • 在ubuntu的 man手册 中有syscall() 的用法和 实现细节 ,非常有用, 可以通过如下命令查看,在man手册中有如下两个表描述了不同的硬件架构,系统调用实现的细节
    man 2 syscall
    
    在这里插入图片描述
    在这里插入图片描述
  • 通过上述两个表,对于怎么实现系统调用相信已经比较清楚了,通过一条软中断指令触发异常,使程序由用户态进入内核态,系统调用号和参数以及返回值则通过寄存器传递。
  • 如下是nolibc中实现的read()函数,架构为arm64,大家可以结合上面两张表分析一下面代码,有关gcc内嵌汇编的语法可以参考我的另外一篇文章《gcc内嵌汇编语法分析
    在这里插入图片描述

2 系统调用流程

第一章节以c标准库为例分析系统调用在用户态的实现,当执行完svc指令进入内核态之后又会执行哪些操作呢?本章将会继续进行讨论。

  • 触发异常后第一步肯定是进入异常向量表,linux异常向量表在文件./linux-orangepi/arch/arm64/kernel/entry.S中实现,这部分代码还是比较复杂的,需要对ARM64的体系架构和gcc汇编器由较为深入的认识,我们只关注大概流程。如下异常向量表中,kernel_ventry是一个宏,异常向量表的第九行kernel_ventry 0, t, 64, sync,展开后为el0t_64_sync,这个函数即为系统调用的入口
    在这里插入图片描述
  • el0t_64_sync也是在./linux-orangepi/arch/arm64/kernel/entry.S通过汇编实现,如下图所示,他主要功能是保存内核传递的参数并调用el0t_64_sync_handler()
    在这里插入图片描述
  • el0t_64_sync_handler()是一个c函数,在./linux-orangepi/arch/arm64/kernel/entry-common.c中实现,系统调用使用svc异常触发,会调用el0_svc()来处理svc异常。
    在这里插入图片描述
  • el0_svc()./linux-orangepi/arch/arm64/kernel/entry-common.c中实现如下,主要是调用do_el0_svc()处理系统调用
    static void noinstr el0_svc(struct pt_regs *regs)
    {
    	enter_from_user_mode(regs);                        // 标记进入内核态,处理状态切换(如关闭用户态调试)
    	cortex_a76_erratum_1463225_svc_handler();          // 针对 Cortex-A76 硬件缺陷的补丁处理
    	do_el0_svc(regs);                                  // 系统调用核心逻辑入口
    	exit_to_user_mode(regs);                           // 准备返回用户态,恢复上下文并执行 eret
    }
    
  • do_el0_svc().//linux-orangepi/arch/arm64/kernel/syscall.c中实现,核心函数是el0_svc_common()
    void do_el0_svc(struct pt_regs *regs)
    {
    	fp_user_discard();
    	/*
    	* regs:用户态传递过来参数的指针
    	* regs->regs[8]:从指针中找到系统调用号
    	* __NR_syscalls:系统调用的总数
    	* sys_call_table:系统调用表
    	*/
    	el0_svc_common(regs, regs->regs[8], __NR_syscalls, sys_call_table);
    }
    
  • sys_call_table./linux-orangepi/arch/arm64/kernel/sys.c中定义,sys_call_table中包含所用系统调用的入口,如下图所示
    在这里插入图片描述
  • el0_svc_common()./linux-orangepi/arch/arm64/kernel/syscall.c中实现,主要功能是依据系统调用号在sys_call_table中找到对应的系统调用入口并执行
  • 至此,系统调用的整个流程分析完成,大家可以试着依据这个流程分析现有的系统调用,也可以试着增加一个系统调用,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值