本篇为《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入口执行之 .
( 注 : 以上分析可以通过反汇编得到验证
# 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入口执行之 .
( 注 : 以上分析可以通过反汇编得到验证