Linux内核模块的“加载”和“卸载”函数

Linux内核模块加载函数一般以_ _init 标识声明,典型的模块加载函数的形式如代码 ---------insmod hello.ko时被调用。
清单4.2所示。
 
代码清单4.2  内核模块加载函数 
1   static int _ _init initialization_function(void) 
2   {  
3   /* 初始化代码 */ 
4   } 
5   module_init(initialization_function); 
模块加载函数必须以“module_init(函数名)”的形式被指定。它返回整型值,若初始
化成功,应返回0。而在初始化失败时,应该返回错误编码。在Linux内核里,错误编码
是一个负值,在中定义,
包含-ENODEV、-ENOMEM之类的符号值。返
回相应的错误编码是种非常好的习惯,因为只有这样,用户程序才可以利用perror等方
法把它们转换成有意义的错误信息字符串。 
在Linux 2.6内核中,可以使用request_module(const char *fmt,  …)函数加载内核
模块,驱动开发人员可以通过调用 
 
request_module(module_name);  
或 
request_module("char-major-%d-%d", MAJOR(dev), MINOR(dev)); 
来加载其他内核模块。 
在Linux内核中,所有标识为_ _init 的函数在连接的时候都放在.init.text这个区段
内,此外,所有的_ _init 函数在区段.initcall.init 中还保存了一份函数指针,在初始化
时内核会通过这些函数指针调用这些_ _init 函数,并在初始化完成后释放init 区段(包

括.init.text,.initcall.init 等)。


Linux内核模块卸载函数一般以_ _exit标识声明,典型的模块卸载函数的形式如代码清-------rmmod hello 时被调用。
单4.3所示。
 
代码清单4.3  内核模块卸载函数 
1  static void _ _exit cleanup_function(void) 
2  { 
3  /* 释放代码 */ 
4  } 
5  module_exit(cleanup_function); 
模块卸载函数在模块卸载的时候执行,不返回任何值,必须以“module_exit(函数
名)”的形式来指定
。 
通常来说,模块卸载函数要完成与模块加载函数相反的功能,如下所示。 
l  若模块加载函数注册了XXX,则模块卸载函数应该注销XXX。 
l  若模块加载函数动态申请了内存,则模块卸载函数应释放该内存。 
l  若模块加载函数申请了硬件资源(中断、DMA通道、I/O 端口和I/O 内存等)
的占用,则模块卸载函数应释放这些硬件资源。 
l  若模块加载函数开启了硬件,则卸载函数中一般要关闭硬件。 


和_ _init 一样,_ _exit 也可以使对应函数在运行完成后自动回收内存。实际上,_ 
_init 和_ _exit 都是宏,其定义分别为:
 
#define _ _init _ _attribute_ _ ((_ _section_ _ (".init.text"))) 
和 
#ifdef MODULE 
#define _ _exit _ _attribute_ _ ((_ _section_ _(".exit.text"))) 
#else 
#define _ _exit _ _attribute_used_ _ _ _attribute_ _ ((_ _section_ 
_(".exit.text"))) 
#endif 
数据也可以被定义为_initdata 和_exitdata,这两个宏分别为: 
#define _ _initdata_ _attribute_ _ ((_ _section_ _ (".init.data"))) 
和 
#define _ _exitdata_ _attribute_ _ ((_ _section_ _(".exit.data"))) 

你可能感兴趣的:(linux内核)