驱动模块 .ko

模块:
模块机制,作用搞高LINUX操作系统的扩充性.
1. 模块概念:

1.动态可加载内核模块LKM

2.内核空间运行
3.是不是一执行文件,是一个没有经过链接,不能独立运行的一个目标文件(.c->.o-->.ko)
4.通insmod命令,把内核模块载入内核空间,rmmod命令 .koc从内核空间移除
5.一个设备的驱动代码对应一个module
6.模块的驱动源代码里面,使用那些头文件是在内核源代码,是不能使用C语言的库存函数

------------------------

2、模块的编写规则:如

 1 #include <linux/module.h>//内核头文件
 2 #include <linux/kernel.h>
 3 
 4 
 5 static int __init test1_init(void) //入口函数  (一般放驱动初始化代码,比如申请资源,注册中断,注册字符设备。。。。)
 6 {
 7     printk("hello world!\n"); //相当于printf()
 8     return 0;
 9 }
10 
11 static void __exit test1_exit(void) //出口函数 (释放初始化那资源)
12 {
13     printk("goodbye!\n");    
14 }
15 
16 
17 module_init(test1_init); //驱动的入口 #insmod *.ko
18 module_exit(test1_exit); //驱动的出口 #rmmod *.ko
19 
20 //#modinfo  *.ko 可以查看module的信息,不是必需的,
21 MODULE_AUTHOR("fbx@GEC");
22 MODULE_DESCRIPTION("the first module of drivers");
23 MODULE_LICENSE("GPL");
24 MODULE_VERSION("V1.0");

 

注意:1、由module_init()指定模块入口函数test_init,像应用程序main(),入口函数返回值 int   0-->代表成功,非0-->失败.

 

 2. 由module_exit()宏 指定出口函数test_exit  , 退出函数返回值  void 

3、 3.MODULE_GLICENSE等宏描述的是当前模块对应的信息

3、模块的编译makefile的编写

 

 1 2.2.1Makefile文件
 2 obj-m += module.o    
 3 KERN_DIR=/home/gec/syscro/kernel/android-kernel-samsung-dev
 4 PWD := $(shell pwd)
 5 modules:    
 6     $(MAKE) -C $(KERN_DIR) M=$(PWD) modules
 7 clean:    
 8     $(MAKE) -C $(KERN_DIR) M=$(PWD) modules clean
 9 
10 ---------------
11 1.obj-m += module.o (module.c) 12 //将驱动源码编译成一个独立的module --> .ko 13 14 2.KERN_DIR=/home/gec/syscro/kernel/android-kernel-samsung-dev 15 驱动源代码在编译时候,所用使用内核源码包的目录路径(跟安装当前模块的内核应一至). 16 17 3.PWD := $(shell pwd) 18 当前目录: 19 20 4.$(MAKE) -C $(KERN_DIR) M=$(PWD) modules 21 $(MAKE) -->make 22 -C $(KERN_DIR) -->转到内核源码包的目录下执行 make -->调用内核源码包根目录下的Makefile --> .o 23 M=$(PWD) modules --> 转回到当前目录下, ---》.ko

 

4、模块的常用操作命令:

insmod:安装LKM

rmmod:删除LKM

modinfo:查看模块的相关信息(也就是模块中最后面的几个宏值得信息)

lsmod:显示当前已加载的模块列表

file:查看文件的属性

size:查看文件的大小

---------------------------------------------

5、__init  __exit这两个宏值

1.__init所修饰代码----> .init.text段
2.如果模块直接参给编译进内核,并不是变成.ko文件再加载,那么__init修饰的函数,在完成初始化后,自动释放_init修饰的函数的资源
3.__exit所修饰代码----> .exit.text段
4.__exit用于驱动变成模块时候,在模块移除时,通知系统实现资源释放

-----------------------------------------

6、printk函数

在内核中,通知console输出的时候,使用printk()
printk和printf的区别
1.在不同空间运行的。
2.printk输出有优先级的,printf没有的
kernel:printk("hello\n");
user :printf("hello\n");

进入内核目录中,cat include/linux/kernel.h :可查看printk打印的优先级:

 1 printk的优先级
 2 #define    KERN_EMERG    "<0>"    /* system is unusable            */
 3 #define    KERN_ALERT    "<1>"    /* action must be taken immediately    */
 4 #define    KERN_CRIT    "<2>"    /* critical conditions            */
 5 #define    KERN_ERR    "<3>"    /* error conditions            */
 6 #define    KERN_WARNING    "<4>"    /* warning conditions            */
 7 #define    KERN_NOTICE    "<5>"    /* normal but significant condition    */
 8 #define    KERN_INFO    "<6>"    /* informational            */
 9 #define    KERN_DEBUG    "<7>"    /* debug-level messages            */
10 
11 printk("hello\n")-->printk(KERN_WARNING "hello\n");  -->printk("<4>" "hello\n")

查看默认优先级:
[@GEC2103 /]# cat /proc/sys/kernel/printk
7 4 1 7
7-->控制台输出的最低优级,优先级的数字小于当前值,才可以输出.
4-->控制台输出的默认优先级
1-->控制台可能最小的优先级

echo  7  5  1 7 >/proc/sys/kernel/printk   //这行命令可以修改内核printk函数的默认优先级

-----------------------------------------------------------

6、内核符号的使用:

4.内核符号

4.1.内核的每个函数与变量都有一个内核符号
add_x()
{

} -----> kstrtab_add_x

4.2内核符号表:
内核符号导出公用后,所公用的内核符号集合

add_x()
{

}
EXPORT_SYMBOL(add_x) //导出为公用,导出之后该函数可以在多个内核模块中使用。

 

posted @ 2016-05-03 19:05  高傲的monkey  阅读(1044)  评论(0)    收藏  举报