范例
程序结构
模块加载函数(必须)
安装模块是被系统自动调用的函数,通过module_init宏来指定,在HelloWorld模块中,模块加载函数为hello_init。一般以__init表示声明。
__init是宏,代表这个函数会放到段“.init.text”
模块卸载函数(必须)
卸载模块是被系统自动调用的函数,通过module_exit宏来指定,在HelloWorld模块中,模块卸载函数为hello_exit。一般以__exit表示声明。
模块加载函数和卸载函数的功能
程序结构
许可证申明(必须)
宏MODULE_LICENSE被用来告知内核,该模块带有一个许可证,没有这样的说明,加载模块时内核会警告。
模块参数 (可选)
通过宏MODULE_PARM指定模块参数,模块参数用于在加载模块时传递参数给模块。
模块作者(可选)
MODULE_AUTHOR(“author”)
PRINTK
printk是内核中出现最频繁的函数之一,通过将printk和printf对比,将有利于大家理解:
1、相同点: 打印信息
2、不同点:printk在内核中使用,printf在应用程序中使用
printk允许根据严重程度,通过附加不同的优先级来对消息分类
PRINTK优先级
在<linux/kernel.h>中定义了8种记录级别。按照优先级递减的顺序分别是:
KERN_EMERG:用于紧急消息,常常是那些崩溃前的消息
KERN_ALERT:需要立刻行动
KERN_CRIT:严重情况,常常与严重的硬件或者软件失效有关
KERN_ERR:用来报告错误情况,设备驱动常常使用KERN_ERR来报告硬件故障
KERN_WARNING:有问题的警告,这些情况自己不会引起系统的严重问题
KERN_NOTICE:正常情况,当是仍然值得注意
KERN_INFO: 信息型消息。在这个级别,很多驱动在启动时打印它们发现硬件信息
KERN_DEBUG:用作调试消息
可以通过下面方法修改打印级别为 n
echo n >/proc/sys/kernel/printk
没有指定优先级的printk默认使用DEFAULT_MESSAGE_LOGLEVELLL优先级,它是一个在kernel/printk.c中定义的整数。
合理使用printk
模块加载、卸载
1、加载: insmod (insmod hello.ko)
2、卸载: rmmod (rmmod hello.ko)
3、查看所有已加载模块 : lsmod
lsmod 命令实际上是读取/proc/modules文件
4、查看某个模块信息: modinfo hello.ko
在/sys/module/目录也可以看到以模块命名的目录。并在该模块目录下,使用 # tree -a 查看该模块的设备树
5、查看输出:
a . dmesg
b . cat /ver/log/messages (带时间)
c . cat /proc/kmsg
模块编译 (Makefile)
模块参数
module_param
module_param(参数名,参数类型,参数读/写权限)
type类型包括以下几种:
charp、 int 、long、shart、uint、ulong、ushort、bool
perm权限包括:
S_IRUGO :只读
S_IWUSR : 只写
S_IRUGO | S_IWUSR : 读写
定义在/include/linux/stat.h中
在加载内核模块时,用户可以向模块传递参数,形式为“insmod 模块名 参数名=参数值 ”,如果不传递,参数将使用模块内定义的缺省值。
模块被加载后,在/sys/module/目录下将出现以此模块命名的目录。
当“参数读/写权限”为0时,表示此 参数不存在sysfs文件系统下对应的文件节点;
如果此模块存在“参数读/写权限”不为0的命令行参数,在此模块的目录下将出现parameters目录,包含一系列以参数命名的文件节点,这些文件的权限值就是传入module_param()的“参数读/写权限”,而文件的内容为参数的值
module_param_array
用于声明数组