标签:
一.基础
1.Linux 内核很庞大,相应的包含的组件也非常多。Linux文件就是常说的zImage和bzImage,在内核启动期间会被解压到内存。
2.如何使用Linux的这些组件呢?一般情况下我们会想到说,让所有的组件都包含在Linux内核文件中,这样一了百了,省事。
但是随之而来的思考是,如果某一个组件在整个系统的运行过程中,只实际运行了1分钟,但是整个系统却要运行一小时,那么剩下的59分钟就是浪费的啊,而且还占据了内存空间。你说多不好,又浪费时间又浪费空间。
3.新的使用组件的思路:动态加载和卸载。也就是需要这个组件的时候才去加载,不需要的时候,就卸载。这边是我们所说的内核模块机制。
4.关于内核模块。有以下特征:
(1)不被编译进内核文件
(2)可以动态加载和卸载
5.关于内核模块的操作
(1)加载insmod
(2)卸载rmmod
(3)查看lsmod
二.设计和编写
1.分析和结构概括
2.代码编写
(1)一般init函数是static int类型的,exit函数式static void类型的
(2)printk和printf的区别是printk最前面需要的是表示优先级的参数
三.Makefile编写
1.需要一个变量指明我们最终产生的内核模块的名字
(1)如果内核模块只有一个源文件,一般模块名称和原文件一样,只是把.c改成.o
obj-m := helloworld.o
(2)如果有多个源文件,那么就应该是模块名可以随便,但是还要多一条语句
模块名-objs := file1.o file2.o file3.o
2.定义一个变量指明内核代码所在的路径。因为模块是基于内核的,你用什么版本的内核作为基础,编译出来的模块只能在同版本的内核使用。
KIR := /内核源代码路径
3. 编写规则,只有目标all,但是没有依赖,却有命令。
make -C $(KDIR) M = $(pwd) modules CROSS_COMPILE = arm-linux ARCH = arm
-C指明要进入-C后面的路径(内核路径)编译模块,M指明了模块文件的路径
4.最后编写clean伪指令,清除产生的中间文件和.ko文件。将ko文件复制到文件系统。
5.rmmod的时候要在/lib/modules目录下面有和内核模块的内核版本一致的目录名
经常用(uname -r)来获取内核版本
mkdir -p /lib/modules/$(uname -r)
6..用tftp 地址 文件名的命令下载内核到sdram,然后用nfs挂载文件系统,启动Linxu系统,之后对内核模块进行操作。
四.模块可选项
1.模块申明
(1)MODULE_LICENSE(“遵守的协议”)
没有这一个申明,在加载模块的时候会报警告。
(2)MODULE_AUTHOR(“作者”)
(3)MODULE_VERSION(“版本”)
(4)MODULE_DESCRIPTION(“功能描述”)
2.模块参数
(1)和普通应用程序一样,在加载模块的时候,可以给模块传递一些参数。
(2)区别在于,要事先申明这些参数的数据类型和变量名字,而且要用到
module_param(name,type,perm)这个宏定义。他用来指明保存模块参数的变量。
name:变量名
type:变量类型,一般是int,bool以及charp(字符串类型,记住是charp,不是char和char*)
perm:权限。一般分为S_IRUGO和S_IWUSR。通常情况下将他们按位或。
3.模块符号导出
(1)当一个模块要使用另一个模块的函数(变量)的时候,如果没有符号导出,不仅要实现这个函数,还要申明这个函数导出给其他模块使用,否则在其他模块使用这个函数的时候会出错,甚至不能加载要使用它的模块。
(2)使用EXPORT_SYMBOL(符号名)或者EXPORT_SYMBOL_GPL(符号名)来申明。后者只可以用于遵循GPL协议的模块。
如果生成多个独立的模块,则在obj-m后面继续添加.o文件。
标签:
原文地址:http://www.cnblogs.com/YanfeiHao/p/4428728.html