1. 如一段模塊的代碼:hellomod.c(點擊)
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> static int __init lkp_init (void) { printk ("<1> Hello, world! from the kernel space...\n"); return 0; } static void __exit lkp_exit (void) { printk ("<1> Goodbye, world! leaving kernel space...\n"); } module_init (lkp_init); module_exit (lkp_exit); MODULE_LICENSE ("GPL");
|
1.1 module_init (lkp_init) 這一段宏展開 :
#define module_init(x) __initcall(x);
#define __initcall(fn) device_initcall(fn)
#define device_initcall(fn) __define_initcall("6",fn,6)
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
所以這段宏是:
static initcall_t __initcall_##fn##6 __used __attribute__((__section__(".initcall" “6” ".init"))) = lkp_init
其中 initcall_t 是函數指針原型: typedef int (*initcall_t)(void);
__initcall_##fn##id 就是函數指針的名稱,它其實是一個變量名稱
__attribute__((__section__(".initcall" level ".init"))) 則表示把對象放在一個這個由括號中的名稱所指代的section中。
所以這一段宏的意思是 申請一個變量名爲 __initcall_lkp_init6 類型爲
typedef int (*initcall_t)(void) 的函數指針,並賦值爲 lkp_init。
1.2 module_exit (lkp_exit) 這一段宏展開 :
#define __exitcall(fn) \
static exitcall_t __exitcall_##fn __exit_call = fn
和上一個宏一樣,定義一個函數變量並賦值。
1.3 MODULE_LICENSE ("GPL") 這一段宏展開:
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
#define __module_cat(a,b) ___module_cat(a,b)
#define __stringify_1(x) #x
#define __stringify(x) __stringify_1(x)
static const char __module_cat(name,__LINE__)[] \
__attribute_used__ \
__attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
展開後形式如下:
static const char
__mod_license24[] __attribute__ ((__used__))
__attribute__((section(".modinfo"),unused)) = "license" "=" "GPL";
(static const char str[] = "license" "=" "GPL"; 上面的型如這個,定義一個字符數組然後給字符數組賦值)
**** 另外注意上邊:
#define ___module_cat(a,b) __mod_ ## a ## b
這一句中的 ## 的用法,(可以自己嘗試着是一下)!!!
1.4 module_param(name, type, perm) 解析