linux内核编程--3系统调用与宏参数字符串化
来源:互联网 发布:2016海外代购数据 编辑:程序博客网 时间:2024/06/16 13:23
系统调用
1. 简介
linux内核中设置了一组用于实现系统功能的子程序,称为系统调用。系统调用和普通库函数调用非常相似,只是系统调用由操作系统核心提供,运行于核心态,而普通的函数调用由函数库或用户自己提供,一般运行于用户态(也可能间接调用系统调用)。
2. 内核系统调用申明与实现
Linux内核提供的系统调用大多声明在文件:include\linux\syscalls.h,而具体函数实现通过宏定义定义在内核系统的各个子模块中。以下以最简单的系统调用:epoll_create(创建epoll句柄)为例,讲解系统调用的申明与实现。
1) 声明
在文件include\linux\syscalls.h中申明了系统调用:
asmlinkage long sys_epoll_create(int size);
函数sys_epoll_create接受一个入参size,自内核2.6.8后此入参其实已经没用,只要求大于0即可:
Since Linux 2.6.8, the size argument is ignored, but mustbe greater than zero;
2) 实现
在内核include\linux\eventpoll.c中,有如下实现:
SYSCALL_DEFINE1(epoll_create,int, size){if (size <= 0) return -EINVAL; return sys_epoll_create1(0);}
将宏SYSCALL_DEFINE1(epoll_create, int, size)展开其实就是asmlinkagelong sys_epoll_create(int size)。宏参数的第一个参数将扩展为系统调用函数:sys_epoll_create,其后所有参数都以type/value形式成对出现,将扩展成函数的入参定义。具体分析如下(SYSCALL_DEFINEX宏解析):
a. 文件include\linux\syscalls.h定义宏SYSCALL_DEFINE1为
#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1,_##name, __VA_ARGS__)
表示此系统调用需要一个入参。
b. SYSCALL_DEFINEx为如下:
#defineSYSCALL_DEFINEx(x, sname, ...) \ SYSCALL_METADATA(sname, x, __VA_ARGS__) \ __SYSCALL_DEFINEx(x,sname, __VA_ARGS__)
c. 由于没有定义CONFIG_FTRACE_SYSCALLS预编译宏,上述第一个宏定义SYSCALL_METADATA定义为空,第二个宏为:
#define__SYSCALL_DEFINEx(x, name, ...) \ asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ __attribute__((alias(__stringify(SyS##name)))); \ static inline longSYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ asmlinkage longSyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ asmlinkage longSyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ { \ long ret =SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ __MAP(x,__SC_TEST,__VA_ARGS__); \ __PROTECT(x,ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ return ret; \ } \ static inline longSYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
d. sys##name会拼接上一层调用宏创建来的name,也就是sname,sname的再上一层是_##name,也就是_epoll_create,最后就变成sys_epoll_create(…),下面请看括号里面的宏参数转换;
e. 有__MAP定义如下:
#define __MAP(n,...) __MAP##n(__VA_ARGS__)所以括号里面的参数就变成:__MAP1(__VA_ARGS__)
有__MAP1如下:
#define __MAP1(m,t,a) m(t,a)所以刚才__MAP(x,__SC_DECL,__VA_ARGS__)就被扩展为__SC_DECL(t,a)
再有__SC_DECL如下:
#define __SC_DECL(t, a) t a
最终括号里面的内容就扩展为:
int size
f. 最终整个__SYSCALL_DEFINEx的第一行就扩展称为------------即函数名定义:
asmlinkage long sys_epoll_create(int size)
也就是函数的实现。
g. __SYSCALL_DEFINEx宏的后面部分是利用__attribute__设置系统调用的别名。用兴趣的读者可以自己展开分析。
宏参数字符串化
在上面的宏内容解析中用到了##,其含义就是以字符串形式拼接后面的参数;还有一个符号:#,含义就是字符串化宏参数。
以下详细讲诉此(#、##)用法:
1. 宏参数字符串化
定义如下宏:
#define STRINGIFY(x)#x#define TOSTRING(x) STRINGIFY(x)
分析:第一个宏是将参数字符串化,第二个宏是将参数宏化(也就是在字符串上加了个括号,使之成为一个独立的整体,相对于提高了优先级)。
2. 宏参数字符串拼接:
#define STR_APPEND2_STR(param1, param2) TOSTRING(param1##param2)
分析:先将两个参数以字符串形式拼接,在将整体字符串化。
测试:
源代码:
ULONG cvtest_Test4_Hong2Str()
{ ULONG ulRet = ERROR_SUCCESS; printf("to_str = %s, append_str = %s\n", TOSTRING(1+1), STR_APPEND2_STR(ABC_, ABC)); return ulRet;}
输出结果:
- linux内核编程--3系统调用与宏参数字符串化
- Linux内核模块编程--系统调用
- Linux内核模块编程-系统调用拦截
- 读薄《Linux 内核设计与实现》(3) - 系统调用
- 《Linux内核设计与实现》--系统调用
- linux内核设计与实现:系统调用
- Linux内核-系统调用
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- (转载) 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 【转载】在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- 华为2016研发工程师编程题2字符集合
- 【Scikit-Learn 中文文档】无监督学习: 寻求数据表示
- CSS(二十四)
- eclipse快捷键
- 用multisim 设计一个13进制计数器
- linux内核编程--3系统调用与宏参数字符串化
- 【Scikit-Learn 中文文档】把它们放在一起
- CSS(二十五)
- realsense r200使用过程记录
- pat1103
- 【Scikit-Learn 中文文档】寻求帮助
- CSS(二十六)
- Lintcode:最大子数组
- 全排列--深度优先搜索