前言
linux系统比较庞大,以前一直是学了忘,忘了学,总是觉得还是不能更深入地了解。今天是一个新的开始,终于决定开始写博客了,而且会一直坚持下去,这么做的目的主要有以下几点:
1.促进自己更好的学习
2.希望能对阅读博客的人有一点点帮助
本文分析linux驱动模块里MODULE_AUTHOR宏的用法和定义,便于深入理解其意义。
1.用法
MODULE_AUTHOR("tuxr");
2.定义
#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
展开为:MODULE_INFO(author,“tuxr”)
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
展开为:__MODULE_INFO(author,author,“tuxr”)
// 连接形参的宏
#define ___module_cat(a,b) __mod_ ## a ## b
#define __module_cat(a,b) ___module_cat(a,b)
#ifdef MODULE
#define __MODULE_INFO(tag, name, info) \
static const char __module_cat(name,__LINE__)[] \
__used __attribute__((section(".modinfo"), unused, aligned(1))) \
= __stringify(tag) "=" info
#else /* !MODULE */
/* This struct is here for syntactic coherency, it is not used */
#define __MODULE_INFO(tag, name, info) \
struct __module_cat(name,__LINE__) {}
#endif
展开为:
static const char __mod_authorXX[] \
__used __attribute__((section(".modinfo"),unused,aligned(1))) \
= "author = tuxr"
从 展开的结果分析MODULE_AUTHOR(“tuxr”)语句定义了一个常数字符串。为了理解该语句必须了解以下几个知识点:
- ##的用法
参考文章C语言宏定义中的#,##,#@及\符号的作用
特别要注意当用##连接形参时,##前后的空格可有可无 - __LINE__内置宏的用法
参考文章 c语言的__LINE__和其它常用宏定义 - __stringify宏的用法
/* Indirect stringification(间接的字符串化). Doing two levels allows the parameter to be a
* macro itself. For example, compile with -DFOO=bar, __stringify(FOO)
* converts to "bar".
*/
#define __stringify_1(x...) #x
#define __stringify(x...) __stringify_1(x)
该宏的目的是把参数字符串化, … 表示可变参数,可参考文章C语言 ## VA_ARGS 宏
- __attribute__关键字的用法
__attribute__关键字在这里用来设置变量的属性,可参考资料Specifying Attributes of Variables
section(".modinfo"):表示该常数变量将被连接到.modinfo部分,再调用函数读取模块信息,比如
version = get_modinfo(info.modinfo, info.modinfo_len, “version”);在这里暂时不深入了!
unused:告诉编译器,该变量可能不会被引用,不要发出警告
aligned(1):表示按1字节对齐
根据以上对MODULE_AUTHOR宏的分析,同样可以展开另两个宏
MODULE_DESCRIPTION("Driver for AM335X GPIO");
MODULE_LICENSE("GPL");
展开结果为:
static const char __mod_descriptionXX[] \
__used __attribute__((section(".modinfo"),unused,aligned(1))) \
= "description= Driver for AM335X GPIO"
static const char __mod_licenseXX[] \
__used __attribute__((section(".modinfo"),unused,aligned(1))) \
= "license= GPL"