<内核模块代码>
1)内核模块内有main()函数
2)首先编写没内核模块相应的函数功能
3)内核模块的入口由一个宏(module_init(),module_exit()),来加载和卸载(实际是指明加载函数和卸载函数,这样内核才会认识)
4)头文件:<linux/init.h><linux/module.h>
例:
#include<linux/init.h>
#include<linux/modules.h>
static int __init hello_init(void)
{
pintk(KERN_WARNING“hello,word ”);
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO“goodby,word ”);
}
module_init(hello_int);
module_exit(hello_exit);
注意:
1)一般都会在函数头前加上static
2)和printf()函数相比,ptintk()打印信息会有一个信息的优先级别,都是以宏的形式出现,如:KERN_WARNING 和KERN_INFO
3)linux中标志为__init的函数在连接的时候都会放在".init.text"这个区段内,另外所有__init函数在.initcall.init还保存了一份函数指针,在初始化内核的时候利用这些指针调用"__init"函数,在初始化完成之后释放"init"区段。(包括".init.text"和".initcall.init")
__init和__exit都是Linux中的宏:
#define __init __attribute__((__section__(".init.text")))
#define __exit __atrribute__((__section__(".exit.text")))
<内核模块的Makefile文件>
格式:
obj-m := helloword.o
hello-objs := file1.o file2.o file3.o file4.o
KDIR= /“path of linux kernel”(注意:实际编写的时候是没有双引号的)
all :
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPLE=arm-linux-
clean:
rm -rf *.o *.ko *.oder *.symvers
Makefile文件分析:
KDIR :用于指定内核代码位置路径
M:用于指定驱动模块代码位置
hello-objs:用于多文件的内核驱动模块
注意:在卸载内核模块的时候,必须在文件系统中的/lib/modules 目录下有指明该模块所对应的内核版本,以表明相互匹配,可以使用命令($(uname -r)),来获取内核版本
<带参数的内核模块>
1 #include <linux/init.h> 2 #include <linux/module.h> 3 MODULE_LICENSE("Dual BSD/GPL"); 4 5 static char *book_name = "dissecting Linux Device Driver"; 6 static int num = 4 000; 7 8 static int book_init(void) 9 { 10 printk(KERN_INFO " book name:%s ",book_name); |
11 printk(KERN_INFO " book num:%d
",num); 12 return 0; 13 } 14 static void book_exit(void) 15 { 16 printk(KERN_INFO " Book module exit "); 17 } 18 module_init(book_init); 19 module_exit(book_exit); 20 module_param(num, int, S_IRUGO); 21 module_param(book_name, charp, S_IRUGO); 22 23 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 24 MODULE_DESCRIPTION("A simple Module for testing module params"); 25 MODULE_VERSION("V1.0"); |
1)声明并定义模块参数
module_param(参数名,参数类型,参数读/写权限)
2)装载模块时想用户空间向模块传递参数
insmode 模块名 参数名=参数值 (注意:参数类型可以是int short long byte uint ushort ulong charp bool )
3)实现该功能的机制
模块被装载后,会在"/sys/module"目录下出现该模块的名字的目录,当"参数读/写权限"为0的时,表示此参数不存在sysfs文件系统下对应的文件节点,如果当"参数读/写权限"不为0的时,在"sys/module"下对应的模块的名字的目录下将出现parameters目录。该目录下包含一系列的以参数名字命名的文件节点。
<导出符号>
1)什么是导出符号
在Linux2.6的"/proc/kallsyms"文件(存在于内存中)对应着内核符号表,他记录了符号(导出的函数或模块)以及符号所在内存中的地址。
2)怎么导出符号
EXPORT_SYMBOL(符号名);
EXPORT_SYMBOL_GPL(符号名);
注意:导出的符号可以被其他模块使用,使用之前进行声明一下即可
3)实例
1 #include <linux/init.h> 2 #include <linux/module.h> 3 MODULE_LICENSE("Dual BSD/GPL"); 4 5 int add_integar(int a,int b) 6 { 7 return a+b; 8 } 9 10 int sub_integar(int a,int b) 11 { |
12 return a-b; 13 } 14 15 EXPORT_SYMBOL(add_integar); 16 EXPORT_SYMBOL(sub_integar); |
在"proc/kallsyms"中的结果如下
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">