非编译到kernel中的驱动程序为什么非要定义:__attribute__((alias(#x)))别名问题
文章来源:http://gliethttp.cublog.cn
非编译到kernel中的驱动程序为什么非要定义:#define MODULE<__attribute__((alias(#x)))别名问题> 本篇为《linux启动时对编译进内核驱动模块的加载》的姊妹篇,主要是module模式下驱动的加载分析. #ifndef MODULE # define MODULE #endif
定义#define MODULE是为了include/linux/init.h头文件中使用模块系统函数,[2007-07-14gliethttp]如使用模块module_init(),在《linux启动时对编译进内核驱动模块的加载》中将到的驱动是不能坚决不能定义MODULE的,因为编译进kernel的模块有编译进kernel模块的专有module_init()定义.#define MODULE后的module_init()定义如下:
typedef int (*__init_module_func_t)(void); typedef void (*__cleanup_module_func_t)(void); #define module_init(x) \ int init_module(void) __attribute__((alias(#x))); \ static inline __init_module_func_t __init_module_inline(void) \ { return x; } #define module_exit(x) \ void cleanup_module(void) __attribute__((alias(#x))); \ static inline __cleanup_module_func_t __cleanup_module_inline(void) \ { return x; } 我们首先需要清楚:int init_module(void) __attribute__((alias(#x)));[gliethttp]这是要作甚? 它是用来告诉编译器将init_module作为#x的别名alias替代#x,举例:另一篇文章《Linux下LED驱动测试源码》http://gliethttp.cublog.cn可找到
...... static int __init led_init( void) {int result; SET_MODULE_OWNER(&led_fops); result = register_chrdev(led_MAJOR, "led",&led_fops); if (result < 0) return result; DBG(" initialized\n"); xLED_Install(); return 0; } ...... module_init(led_init); ...... 经过module_init(led_init);之后led_init被别名init_module取代,所以可以理解为: ...... int init_module( void) //static int __init led_init( void)被编译器干掉了,由int init_module( void)取代 {int result; SET_MODULE_OWNER(&led_fops); result = register_chrdev(led_MAJOR, "led",&led_fops); if (result < 0) return result; DBG(" initialized\n"); xLED_Install(); return 0; } ...... 这样可以不用显式的声明init_module,而是使用更具有模块化、人性化的名字led_init来让人更容易理解的定义入口,之后insmod解析init_module入口执行之.
(注:以上分析可以通过反汇编得到验证[gliethttp])
|
阅读(2334) | 评论(0) | 转发(0) |