内核 模块开发
linux内核的整体结构非常庞大,组件合成分为2种:
(1):把所有的组件都编译进内核文件,即zImage或bzImage。这种有两个缺点:
a、生成的内核文件过大。
b、如果想要添加或删除某个组件,需要重新编译整个内核。
(2)内核模块机制:需要该组件时,动态地添加到正在运行的内核中。
内核模块特点:
(1)模块本身并不被编译进内核文件(ZImage/bzImage).
(2)可以根据需求,在内核运行期间动态的安装或卸载。
模块加载函数:
安装模块时被系统自动调用的函数,通过module_init宏来指定,如hello_init。
模块卸载函数:
卸载模块时被系统自动调用的函数,通过module_exit宏来指定,如hello_exit。
模块编译:在linux2.6下编译内核模块,通常使用makefile
单个源文件(hello.c)编译:
ifneq ($(KERNELRELEASE),) //如果KERNELRELEASE不等于空 obj-m := hello.o else KDIR := /lib/modules/2.6.18-53.el5/build //内核源代码路径 all: make -C $(KDIR) M=$(PWD) modules //modules:makefile的目标,
//-C:进入后面紧跟的目录中使用它的makefile来编译,后面紧跟的是一个目录。
//M:build文件中要求的,表示内核代码所在。
clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers endif
多个源文件(main.c add.c)编译
ifneq (($KERNELRELEASE),) obj-m := hello.o //内核模块的名字 hello-objs := main.o add.o //hello-objs中hello与模块名字必须一样,如果多个文件,add文件名 else KDIR := /lib/modules/2.6.18-53.el5/build all: make -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers endif
1.加载insmod (insmod hello.ko)
2.卸载rmmod (rmmod hello)
3.查看 lsmod
4.加载modprobe (modprobe hello)
modprobe如同insmod,也就是加载一个模块到内核。它的不同之处在于它会根据文件
/lib/modules/<$version>/modules.dep
来查看要加载的模块,看它是否还依赖于其他模块,如果是,modprobe会首先找到这些模块,把它们先加载到内核。
1.许可证申明:
宏MODULE_LICENSE用来告知内核,该模块遵守的许可证协议,如“GPL”、“GPL v2”。
MODULE_LICENSE("遵守的协议")
MODULE_LICENSE("GPL")
2.作者申明
MODULE_AUTHOR("作者")
3.模块描述
MODULE_DESCRIPTION("模块的功能描述")
4.模块版本
MODULE_VERSION("V1.0")
5.模块别名
MODULE_ALIAS("别名");
6.模块参数:通过宏module_param指定保存模块参数的变量。模块参数用于在加载模块时传递参数给模块。
module_param(name,type,perm)
name:变量的名称
type:变量类型,bool:布尔型 int:整形 charp:字符串型
perm是访问权限。 S_IRUGO:读权限 S_IWUSR:写权限
如:
在hello.c中 int a = 9; module_param(a,int,S_IRUGO); 命令行中输入:insmod test.ko a=100 //把100赋给a
内核符号导出:
EXPORT_SYMBOL(符号名)
EXPORT_SYMBOL_GPL(符号名) //只能用于包含GPL许可证的模块
如两个模块A、B模块:需在A(定义变量或者函数)中利用EXPORT_SYMBOL(符号名)导出,在B模块中用extern 再声明下。
uname -r //查看内核版本
内核打印:printk。允许根据严重程度,通过附加不同的“优先级”来对消息分类
printk(KERN_WARNING "hello world");
printk("<0> hello world");
在<linux/kernel.h>中定义了8种记录级别:
KERN_EMERG "<0>" 紧急消息
KERN_ALERT "<1>" 需要立即处理
KERN_CRIT "<2>" 严重情况
KERN_ERR "<3>" 错误情况
KERN_WARNING "<4>" 有问题的警告
KERN_NOTICE "<5>" 正常情况,但仍然需要注意
KERN_INFO "<6>" 信息型消息
KERN_DEBUG "<7>" 用作调试消息
注意:没有指定优先级printk默认使用DEFAULT_MESSAGE_LOGLEVEL优先级,定义在kernel/printk.c中
如:
#define DEFAULT_MESSAGE_LOGLEVEL 4
屏幕上没有打印的消息全在:/var/log/message
内核打印控制台优先级配置
在/proc/sys/kernel/printk文件中,cat /proc/sys/kernel/printk
6 4 1 7 //console_loglevel default_message_loglevel minimum_console_level default_console_loglevel