Linux系统调用源码分析(一)

Linux系统调用是操作系统所实现的应用编程接口(Application Programming Interface,API),说简单点就是Linux内核对外提供的接口函数,对外就是指对一个个进程而言,进程通过调用系统调用完成自身需的全部功能。

图片

系统调用在每个平台的实现方式都不相同,x86通过指令int 0x80实现;arm通过指令svc实现;之后会详细介绍系统调用流程,现在先以open为例讲一下系统调用的定义。

图片

如果我们要在内核中增加一个系统调用,首先如上图所示定义一个函数声明。

537行,声明在open前面加上sys_以组成系统调用sys_open的声明。

此函数声明看似简单,只是一个带有三个参数的普通函数,可是如果不知道系统调用辅助宏,用grep是永远也找不到sys_open的具体实现的。

 

所以让我们先来看一下与系统调用相关的辅助宏定义:

图片

184行,SYSCALL_DEFINE3宏用于定义带有3个参数的系统调用。

194行,__SYSCALL_DEFINEx把定义的拆解成数字参数及参数列表,并定义与此系统调用相关的函数,及编译选项。

 

知道了系统调用的辅助宏,那么就来看看open的具体定义

图片

1070行,只有一行代码就把open系统调用的函数定义,及辅助函数都定义出来了。

1071~1076行,就是此open系统调用的具体实现,如果在这里添加printk函数是可以编译通过,并在运行时打印调试信息的。

 

在这里,顺便提一下openat函数,从2.6.16版本开始,Linux引入opeant系统调用,同open相比,多了一个dirfd参数。引入openat方便一个进程内的各线程拥有不同的当前目录,传统的chdir会影响整个进程,而使用openat只需要每个线程在初始化时打开一个目录就可以在“当前目录”操作文件了。用cat打开一个文件,调用的就是openat函数。

 

回到系统调用的定义,我们把SYSCALL_DEFINE3宏展开,会得到如下所示代码:

图片

编译器自动生成的代码比较复杂,但主要就是生成两个gcc内置函数用于安全性检查等,它们都是编译时函数,而非运行时函数,跟sizeof和typeof一样只在编译时起作用。

type __builtin_choose_expr (const_exp, exp1, exp2)

这个函数的第一个参数必须是常量表达式,如果const_expr的结果真,那么生成exp1,且返回exp1的类型type;否则生成exp2,并且返回exp1的类型type。如上图第15、18、21、25、28、31行所示。

__builtin_types_compatible_p(typeof(a), typeof(b))

这个是比较两个类型是否相同。如果a为0LL或0ULL时,等于LL类型,否则为0L类型。当然这在32位系统上比较才有意义,64位系统L和LL都为8个字节。

 

把编译器生成的代码化简后并拼接上open的实现代码,就组成了open系统调用的最终代码,如下图:

图片

10,11行,系统调用sys_open通过编译器属性指定函数别名SyS_open。

16~20行,调用进来后,直接调用SYSC_open函数,次函数是系统调用真正的实现函数。

27行,SYSC_open最终通过调用do_sys_open函数实现全部系统调用功能。

 

以上就是一个系统调用所要实现的全部代码,但这样还不够的,还要把系统调用函数写进全局的系统调用列表里,此列表定义如下:

图片

52行,定义系统全局系统调用列表sys_call_table,以4KB对齐。

54行,包含系统调用列表项的具体定义,最终包含如下图所示代码。

图片

这样,sys_open系统调用的入口就写入sys_call_table列表里了。

 

至此,系统调用的定义部分的源码分析就讲完了。

 

原文:https://mp.weixin.qq.com/s/tMprnGDluNaM-4GRu-oC1Q

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值