源代码解析:宏MODULE_LICENSE("Dual BSD/GPL")的展开
MODULE_LICENSE()在module.h定义为
#define MODULE_LICENSE(_license) MODULE_INFO(license, _license)
MODULE_INFO定义为
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
在moduleparam.h中__MODULE_INFO定义为
#define ___module_cat(a,b) __mod_ ## a ## b
#define __module_cat(a,b) ___module_cat(a,b)
#define __MODULE_INFO(tag, name, info) \
static const char __module_cat(name,__LINE__)[] \
__attribute_used__ \
__attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
__stringify(tag)在stringify.h中
#define __stringify_1(x) #x
#define __stringify(x) __stringify_1(x)
这个宏够复杂的,我就想看看预处理后这个宏变成了什么。
和前篇一样
[root@localhost helloworld]# gcc -I /lib/modules/2.6.23.1-4/build/include -E -P -< hello.c > hhhhh.c
In file included from /lib/modules/2.6.23.1-4/build/include/linux/module.h:9,
from <stdin>:5:
/lib/modules/2.6.23.1-4/build/include/linux/list.h:970:2: warning: #warning "don't include kernel headers in userspace"
In file included from /lib/modules/2.6.23.1-4/build/include/linux/module.h:20,
from <stdin>:5:
/lib/modules/2.6.23.1-4/build/include/asm/module.h:64:2: error: #error unknown processor family
这个报错把我搞傻了,"don't include kernel headers in userspace"这句话让我挠头,在makefile中改也没搞定,有知道的告诉我一声。
没办法,就用蠢办法,修改hello.c
#define MODULE_LICENSE(_license) MODULE_INFO(license, _license)
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
#define ___module_cat(a,b) __mod_ ## a ## b
#define __module_cat(a,b) ___module_cat(a,b)
#define __MODULE_INFO(tag, name, info) \
static const char __module_cat(name,__LINE__)[] \
__attribute_used__ \
__attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
#define __stringify_1(x) #x
#define __stringify(x) __stringify_1(x)
MODULE_LICENSE("Dual BSD/GPL");
int main()
{
return 1;
}
是的,我就是只想看看
MODULE_LICENSE("Dual BSD/GPL");变成什么
特别要提的是__LINE__是当前的行号,对于调用是调用时的行号,
接着来吧
gcc -E -P -< hello.c > hh.c
结果hh.c是
static const char __mod_license16[] __attribute_used__ __attribute__((section(".modinfo"),unused)) = "license" "=" "Dual BSD/GPL";
int main()
{
return 1;
}
至于__attribute_used__这些修饰符,我暂时也不确定是什么用的,虽然看了gcc的手册,__attribute_unused__好像是表示在修饰的函数未使用的情况下不出现警告。
有两点还要说的,一个是那个section(".modinfo"),我只知道这是模块结构中的一个段,对于我们原先的hello模块(不是这个,是以前那个),段信息如下
[guobamantou@localhost helloworld]$ objdump -t hello.o
hello.o: file format elf32-i386
SYMBOL TABLE:
00000000 l df *ABS* 00000000 hello.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .rodata.str1.1 00000000 .rodata.str1.1
00000000 l F .text 00000011 hello_exit
00000011 l F .text 00000013 hello_init
00000000 l d .modinfo 00000000 .modinfo
00000000 l O .modinfo 00000015 __mod_license6
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .comment 00000000 .comment
00000000 *UND* 00000000 printk
00000011 g F .text 00000013 init_module
00000000 g F .text 00000011 cleanup_module
使用modinfo命令
[root@localhost helloworld]# /sbin/modinfo hello.ko
filename: hello.ko
license: Dual BSD/GPL
srcversion: ABC142F4744F0BE5A5047D1
depends:
vermagic: 2.6.23.1-4 SMP mod_unload 686
可见modinfo这个段的信息(modinfo命令学自http://linux.chinaunix.net/bbs/archiver/?tid-963292.html)
第二。就是那个字符串的初始化,static const char __mod_license16[]="license" "=" "Dual BSD/GPL";这显然是我们不习惯了,试过了,的确是可以的。看过《C++编程思想》的读者也许记得书中讲过类似 char str[]="xxxx"
"11111";
这样换行的赋值都是正确的。
#define MODULE_LICENSE(_license) MODULE_INFO(license, _license)
MODULE_INFO定义为
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
在moduleparam.h中__MODULE_INFO定义为
#define ___module_cat(a,b) __mod_ ## a ## b
#define __module_cat(a,b) ___module_cat(a,b)
#define __MODULE_INFO(tag, name, info) \
static const char __module_cat(name,__LINE__)[] \
__attribute_used__ \
__attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
__stringify(tag)在stringify.h中
#define __stringify_1(x) #x
#define __stringify(x) __stringify_1(x)
这个宏够复杂的,我就想看看预处理后这个宏变成了什么。
和前篇一样
[root@localhost helloworld]# gcc -I /lib/modules/2.6.23.1-4/build/include -E -P -< hello.c > hhhhh.c
In file included from /lib/modules/2.6.23.1-4/build/include/linux/module.h:9,
from <stdin>:5:
/lib/modules/2.6.23.1-4/build/include/linux/list.h:970:2: warning: #warning "don't include kernel headers in userspace"
In file included from /lib/modules/2.6.23.1-4/build/include/linux/module.h:20,
from <stdin>:5:
/lib/modules/2.6.23.1-4/build/include/asm/module.h:64:2: error: #error unknown processor family
这个报错把我搞傻了,"don't include kernel headers in userspace"这句话让我挠头,在makefile中改也没搞定,有知道的告诉我一声。
没办法,就用蠢办法,修改hello.c
#define MODULE_LICENSE(_license) MODULE_INFO(license, _license)
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
#define ___module_cat(a,b) __mod_ ## a ## b
#define __module_cat(a,b) ___module_cat(a,b)
#define __MODULE_INFO(tag, name, info) \
static const char __module_cat(name,__LINE__)[] \
__attribute_used__ \
__attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
#define __stringify_1(x) #x
#define __stringify(x) __stringify_1(x)
MODULE_LICENSE("Dual BSD/GPL");
int main()
{
return 1;
}
是的,我就是只想看看
MODULE_LICENSE("Dual BSD/GPL");变成什么
特别要提的是__LINE__是当前的行号,对于调用是调用时的行号,
接着来吧
gcc -E -P -< hello.c > hh.c
结果hh.c是
static const char __mod_license16[] __attribute_used__ __attribute__((section(".modinfo"),unused)) = "license" "=" "Dual BSD/GPL";
int main()
{
return 1;
}
至于__attribute_used__这些修饰符,我暂时也不确定是什么用的,虽然看了gcc的手册,__attribute_unused__好像是表示在修饰的函数未使用的情况下不出现警告。
有两点还要说的,一个是那个section(".modinfo"),我只知道这是模块结构中的一个段,对于我们原先的hello模块(不是这个,是以前那个),段信息如下
[guobamantou@localhost helloworld]$ objdump -t hello.o
hello.o: file format elf32-i386
SYMBOL TABLE:
00000000 l df *ABS* 00000000 hello.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .rodata.str1.1 00000000 .rodata.str1.1
00000000 l F .text 00000011 hello_exit
00000011 l F .text 00000013 hello_init
00000000 l d .modinfo 00000000 .modinfo
00000000 l O .modinfo 00000015 __mod_license6
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .comment 00000000 .comment
00000000 *UND* 00000000 printk
00000011 g F .text 00000013 init_module
00000000 g F .text 00000011 cleanup_module
使用modinfo命令
[root@localhost helloworld]# /sbin/modinfo hello.ko
filename: hello.ko
license: Dual BSD/GPL
srcversion: ABC142F4744F0BE5A5047D1
depends:
vermagic: 2.6.23.1-4 SMP mod_unload 686
可见modinfo这个段的信息(modinfo命令学自http://linux.chinaunix.net/bbs/archiver/?tid-963292.html)
第二。就是那个字符串的初始化,static const char __mod_license16[]="license" "=" "Dual BSD/GPL";这显然是我们不习惯了,试过了,的确是可以的。看过《C++编程思想》的读者也许记得书中讲过类似 char str[]="xxxx"
"11111";
这样换行的赋值都是正确的。