4.5 模块参数
可以用“module_param(参数名,参数类型,参数读/写权限)”为模块定义一个参数,例如下列代码定义了1个整型参数和1个字符指针参数:
static int book_num = 4000;
module_param(book_num, int, S_IRUGO);
static char *book_name = "Linux Device Driver";
module_param(book_name, charp, S_IRUGO);
在装载内核模块时,用户可以向模块传递参数,形式为“insmode(或modprobe)模块名 参数名=参数值”,如果不传递,参数将使用模块内定义的缺省值。如果模块被内置,就无法insmod了,但是bootloader(U-boot)可以通过在bootargs里设置“模块名.参数名=值”的形式给该内置的模块传递参数。
参数类型可以是byte、short、ushort、int、uint、long、ulong、charp(字符指针)、bool或invbool(布尔的反),在模块被编译时会将module_param中声明的类型与变量定义的类型进行比较,判断是否一致。除此之外,模块也可以拥有参数数组,形式为“module_param_array(数组名,数组类型,数组长,参数读/写权限)”。
模块被加载后,在/sys/module/目录下将出现以此模块名命名的目录。当“参数读/写权限”为0时,表示此参数不存在sysfs文件系统下对应的文件节点,如果此模块存在“参数读/写权限”不为0的命令行参数,在此模块的目录下还将出现parameters目录,其中包含一系列以参数名命名的文件节点,这些文件的权限值就是传入module_param()的“参数读/写权限”,而文件的内容为参数的值。运行insmod或modprobe命令时,应使用逗号分隔输入的数组元素。
现在定义一个包含两个参数的模块,并观察模块加载时被传递参数和不传递参数时的输出。
代码清单4.4 带参数的内核模块,源代码文件:
#include <linux/init.h>
#include <linux/module.h> // module.h:17:#include <linux/moduleparam.h> 间接包含头文件
#define DRIVER_AUTHOR "xz@vi-chip.com.cn"
#define DRIVER_DESC "A sample driver"
static int book_num = 4000;
module_param(book_num, int, S_IRUGO);
static char *book_name = "Linux Device Driver";
module_param(book_name, charp, S_IRUGO);
static int __init hello_init(void)
{
printk(KERN_INFO "vichip hello_init\n");
printk(KERN_INFO "book num:%d\n", book_num);
printk(KERN_INFO "book name:%s\n", book_name);
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "vichip hello_exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_VERSION("v1.0");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_ALIAS(DRIVER_DESC);
Makefile:
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
else
obj-m := hello_world.o
endif
对上述模块运行“insmod hello_world.ko”命令加载,相应输出都为模块内的默认值,通过查看“dmesg”日志文件可以看到内核的输出:
[29838.775347] book num:4000
[29838.775350] book name:Linux Device Driver
当用户运行“sudo insmod hello_world.ko book_num=200 book_name='Linux Kernel'”命令时,输出的是用户传递的参数:
[29922.817510] book num:200
[29922.817513] book name:Linux Kernel
另外,在/sys目录下,也可以看到hello_world模块的参数:
cd /sys/module/hello_world/parameters/
ubuntu@ubuntu2018:/sys/module/hello_world/parameters$ tree -a
.
├── book_name
└── book_num
0 directories, 2 files
可以通过“cat book_name”和“cat book_num”查看它们的值。