首页 > 代码库 > 嵌入式工程师成长路--------内核模块1

嵌入式工程师成长路--------内核模块1

内核模块分析

这里主要分析一下内核模块中各语句的作用,下面是一段简单的模块代码,只做了模块的初始化和退出操作

 1 #include <linux/module.h>
 2 #include <linux/init.h>
 3 #include <linux/kernel.h>
 4 
 5 static int __init first_module_init(void)
 6 {
 7   printk(KERN_ALERT"Module init!\n");
 8 }
 9 
10 static void __exit first_module_exit(void)
11 {
12   printk(KERN_ALERT"Module exit!\n");
13 }
14 
15 module_init(first_module_init);
16 module_exit(first_module_exit);
17 MODULE_LICENSE("GPL");
18 MODULE_AUTHOR("STAR");
19 MODULE_DESCRIPTION("First Module");

代码简析

  1. 一个内核模块至少包含两个函数:初始化函数,在模块加载到内核时被调用。卸载函数,在内核模块被卸载时调用。
  2. 模块“初始化”和“卸载”函数可以起任意的名字。通过宏module_init()声明初始化函数,通过module_exit()声明卸载函数。
  3. 任何内核模块都需要包含linux/module.h文件。

代码详析

1.first_module_init()函数是模块的入口点,在模块装载时被调用。

  • module_init()是一个宏调用,它唯一的参数便是模块的初始化函数。
  • 模块的所有初始化函数必须符合下面的形式:int name_init(void);
  • 该模块入口函数通常不会被外部函数直接调用,所以它一般被标记为static类型。
  • init函数会返回一个int型的数值,如果初始化顺利完成,那么它的返回值为0,否则返回非0。

2.first_module_exit()函数是模块的出口函数,在模块从内存中卸载时调用。

  • 退出函数必须符合以下形式:void name_exit(void);
  • 与init函数一样,也可以标记其为static。

 

关于 __init和 __exit宏

  1. 如果该模块被编译进内核,而不是动态加载,则宏 __init的使用会在初始化完成后丢弃该函数并收回所占内存。
  2. 如果该模块被编译进内核,宏 __exit将忽略“清理收尾”的函数。
  3. 这些宏在头文件linux/init.h定义。

 

内核模块证书和内核模块文档说明

  1. 2.4内核后,引入识别代码是否在GPL许可下发布的机制。在使用非公开的源代码产品时会得到警告。通过宏MODULE_LICENSE("GPL"),设置模块遵守GPL证书,取消警告信息。
  2. MODULE_DESCRIPTION()用来描述模块的用途。
  3. MODULE_AUTHOR()用来声明模块的作者。  
  4. 这些宏都在头文件linux/module.h定义。使用这些宏只是用来提供识别信息。

 

注  意  

在上面的程序中初始化和退出函数都只是简单的打印一句话。这里用的是printk()函数。printk相当于是内核中的printf,它们区别主要在于指向空间的不同。

内核中,信息一般保存于在内核空间分配的缓冲区中。printf一般指向用户空间,使用printk可改变指向使之指向内核空间。这里只作简要提醒,读者如有需要可到网上查询相关信息。

 

谢谢阅读,转载请注明!

                                                          2017-04-16

 

 

嵌入式工程师成长路--------内核模块1