1.定义
显然SYSCALL_DEFINE1是系统调用的入口,其中1表示函数参数的个数,name表示系统调用函数的名字,同理下面的2,3,4,5,6表示参数个数。其具体定义位于linux-4.13.16\include\linux\syscalls.h中,具体定义如下:

#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)

后面的展开中##是C语言定义的替换符号或连接符,_##name即将name变为_name以作为未来系统调用名称的存根;__VA_ARGS__是可变参数宏,此处即代指…
2.SYSCALL_DEFINEx

#define SYSCALL_DEFINEx(x, sname, ...)               \SYSCALL_METADATA(sname, x, __VA_ARGS__)            \__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)

显然Marco SYSCALL_DEFINEx展开为两个宏,依次解析:

[1] SYSCALL_METADATA(sname, x,__VA_ARGS__)
#ifdef CONFIG_FTRACE_SYSCALLS
...                                                 \
#define SYSCALL_METADATA(sname, nb, ...)            \
...                                                 \static struct syscall_metadata __used          \__syscall_meta_##sname = {                \.name      = "sys"#sname,           \.syscall_nr    = -1,  /* Filled in at boot */ \.nb_args   = nb,              \.types     = nb ? types_##sname : NULL,   \.args      = nb ? args_##sname : NULL,    \.enter_event   = &event_enter_##sname,        \.exit_event    = &event_exit_##sname,     \.enter_fields  = LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \};                         \static struct syscall_metadata __used          \__attribute__((section("__syscalls_metadata")))  \*__p_syscall_meta_##sname = &__syscall_meta_##sname;
#else
#define SYSCALL_METADATA(sname, nb, ...)
#endif

易得该宏依赖于CONFIG_FTRACE_SYSCALLS内核配置选项。若该内核配置选项开启,宏SYSCALL_METADATA 执行头文件include/trace/syscall.h中syscall_metadata结构的初始化,该结构中包含多种有用字段例如系统调用的名称,系统调用表中的编号、参数个数、参数类型列表等,本质是为了添加跟踪信息;若内核配置时 CONFIG_FTRACE_SYSCALLS 未开启,此时宏 SYSCALL_METADATA扩展为空字符串。

[2] __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)

在正式解析该marco之前,先简单介绍几个Marco定义如下:

#define __SC_DECL(t, a)  t a         //该宏可以用作类型和参数组合
...
#define __MAP0(m,...)
#define __MAP1(m,t,a) m(t,a)
#define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__)
#define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__)
#define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__)
#define __MAP5(m,t,a,...) m(t,a), __MAP4(m,__VA_ARGS__)
#define __MAP6(m,t,a,...) m(t,a), __MAP5(m,__VA_ARGS__)
#define __MAP(n,...) __MAP##n(__VA_ARGS__)//函数有几个参数就调用对应的组合函数依次调用对应组合函数最终可得所有参数及其类型

下面是__SYSCALL_DEFINEx的实现:

#define __SYSCALL_DEFINEx(x, name, ...)                  \asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))  \...                         \...                         \static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))

只需关注第一项展开即可,其余展开函数是__SYSCALL_DEFINEx生成的,此处无需深究。研究第一项函数asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)),其中__VA_ARGS__应当表示发起系统调用的函数的参数类型及值,比如说write函数的__VA_ARGS__应当有6项,包括int,fd, const void,*buf, size_t,count6项。而经过对上面__MAP宏的分析可以知道,其会将这6个参数重新组合成为int fd, const void *buf, size_t count 这三项,进而作为系统调用函数sys_write()的参数。
以上就是对系统调用入口宏SYSCALL_DEFINEx的剖析,下面就以read函数为例进行实践。
3.read函数
在linux-4.13.16\fs\read_write.c文件中其系统调用如下所示:
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count);
经过对宏展开后可得:
sys_read(unsigned int fd, char __user * buf, size_t count);

SYSCALL_DEFINEx宏源码解析相关推荐

  1. 最全面的gtest的TEST宏源码解析及自动调度机制

    GTEST的TEST原理分析及自动调度解析 介绍 Gtest是google开发的一个开源的C++测试框架,可在Linux, Windows,Mac多个平台上对C++源码进行测试,它提供了丰富的断言.可 ...

  2. libev源码解析——定时器监视器和组织形式

    我们先看下定时器监视器的数据结构.(转载请指明出于breaksoftware的csdn博客) /* invoked after a specific time, repeatable (based o ...

  3. libev源码解析——调度策略

    在<libev源码解析--监视器(watcher)结构和组织形式>中介绍过,监视器分为[2,-2]区间5个等级的优先级.等级为2的监视器最高优,然后依次递减.不区分监视器类型和关联的文件描 ...

  4. Redis源码解析——双向链表

    相对于之前介绍的字典和SDS字符串库,Redis的双向链表库则是非常标准的.教科书般简单的库.但是作为Redis源码的一部分,我决定还是要讲一讲的.(转载请指明出于breaksoftware的csdn ...

  5. 深度学习框架Caffe源码解析

    作者:薛云峰(https://github.com/HolidayXue),主要从事视频图像算法的研究, 本文来源微信公众号:深度学习大讲堂.  原文:深度学习框架Caffe源码解析  欢迎技术投稿. ...

  6. QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数

    版权声明 请尊重原创作品.转载请保持文章完整性,并以超链接形式注明原始作者"tingsking18"和主站点地址,方便其他朋友提问和指正. QT源码解析(一) QT创建窗口程序.消 ...

  7. webbench源码解析

    webbench源码解析 webbench简介 webbench是一款用C编写的开源工具,主要用来在Linux下进行网站压力测试.最多可以模拟3万个连接去测试网站的负载能力,并可以设置运行的客户端数. ...

  8. prometheus变量_TiKV 源码解析系列文章(四)Prometheus(下)

    本文为 TiKV 源码解析系列的第四篇,接上篇继续为大家介绍 rust-prometheus.上篇主要介绍了基础知识以及最基本的几个指标的内部工作机制,本篇会进一步介绍更多高级功能的实现原理. 与上篇 ...

  9. yolov3之pytorch源码解析_springmvc源码架构解析之view

    说在前面 前期回顾 sharding-jdbc源码解析 更新完毕 spring源码解析 更新完毕 spring-mvc源码解析 更新完毕 spring-tx源码解析 更新完毕 spring-boot源 ...

最新文章

  1. 唯品会实时计算平台的演进之路
  2. Data Lake Analytics: 使用DataWorks来调度DLA任务
  3. android开发百度地图坐标偏差,利用百度地图Android sdk高仿微信发送位置功能及遇到的问题...
  4. FullCalendar 七:FullCalendar应用——整合农历节气和节日
  5. 诗与远方:无题(三十九)
  6. Oracle listagg去重distinct三种方法总结
  7. 淘宝客APP如何配置阿里妈妈sdk详细教程(uniapp配置)
  8. 软件项目开发流程逻辑图
  9. win7浏览器主页修改不过来_win7无法修改ie浏览器主页的解决方法
  10. 系统盘无损迁移至固态硬盘(机械硬盘)
  11. 解决ionic 中 $ionicHistory.goBack()无法返回问题
  12. KTorrent for KDE 4 已抵达
  13. XiaoHu日志 6/17~6/19
  14. arma模型_R语言: GARCH模型股票交易量的研究道琼斯股票市场指数
  15. c语言中如何求双胞胎素数,征求好的算法:输出十万以内的双胞胎素数
  16. Xshell如何配置并远程连接Linux服务器详解
  17. 京东2016招聘笔试题分苹果Java代码
  18. java hashmap api_JAVA基础学习-集合三-Map、HashMap,TreeMap与常用API
  19. 使用while循环方式打印100以内4的倍数(while中加if)、使用while循环方式计算2+4+6+8+...+100、编写程序“从键盘读入个数不正确的整数,并判断读入的正数和负数的个数
  20. 【电机控制不得不学习的干货:】 飞思卡尔MCU正交编/解码器模块

热门文章

  1. SaaS最通俗易懂的解释是什么?看这篇就够了
  2. PAT_乙级_1006_筱筱
  3. 大数据工程师岗位JD中最常出现的技能
  4. 电脑无法连接WiFi,右下角显示红叉解决方法
  5. 数据仓库概念以及选型
  6. ubuntu的gnome桌面重启
  7. 迷你星域冒险服务器维护中,迷你世界星域冒险攻略 星域冒险快速通关技巧[多图]...
  8. crm day03 创建市场活动
  9. 【VSCode常用插件】Path Autocomplete(@路径提示的插件)
  10. ArcGIS笔记2_如何将经纬度WGS84地理坐标系转换为米单位CGCS2000投影坐标系