Table of Contents
1. 概述:
主要区别就是用户可否在系统启动或模块装载时为参数指定相应值,在驱动程序里,参数的用法如同全局变量。
- 不使用module_param
如只定一个全局变量:
#define MY_MAJOR 0x09
static int global_val_test = MY_MAJOR;
那么编译模块后,insmod加载模块时不能传参数进去,如:
[root@bogon hello_world]# insmod first_hello.ko global_val_test=5
insmod: ERROR: could not insert module first_hello.ko: Invalid parameters
同时,insmod模块后,对应module目录下的对应模块下不会生成parameter子目录,更不会生成参数文件.
[root@bogon hello_world]# cat /sys/module/first_hello/
coresize holders/ initsize initstate notes/ refcnt rhelversion sections/ srcversion taint uevent version
- 使用module_param后,参考如下:
#define MY_MAJOR 0x09
static int global_val_test = MY_MAJOR;
module_param(global_val_test, int, 0644);
再编译模块后,再insmod加载模块时就可以传参数进去了,如:
[root@bogon hello_world]# insmod first_hello.ko global_val_test=5
[root@bogon hello_world]# tail /var/log/messages
May 26 14:20:08 localhost kernel: [63460.994397] global_val_test = 5
May 26 14:20:08 localhost kernel: [63460.994409] hello world enter
May 26 14:20:08 localhost kernel: global_val_test = 5
May 26 14:20:08 localhost kernel: hello world enter
同时,在模块目录下会生成parameter目录及参数文件,如下:
[root@bogon hello_world]# cat /sys/module/first_hello/
coresize holders/ initsize initstate notes/ parameters/ refcnt rhelversion sections/ srcversion taint uevent version
[root@bogon hello_world]# ls -alt /sys/module/first_hello/parameters/
total 0
-rw-r--r-- 1 root root 16384 May 26 14:54 global_val_test
2. module_param定义:
函数原型:
/**
* module_param - typesafe helper for a module/cmdline parameter
* @name: the variable to alter, and exposed parameter name.
* @type: the type of the parameter
* @perm: visibility in sysfs.
*
* @name becomes the module parameter, or (prefixed by KBUILD_MODNAME and a
* ".") the kernel commandline parameter. Note that - is changed to _, so
* the user can use "foo-bar=1" even for variable "foo_bar".
*
* @perm is 0 if the the variable is not to appear in sysfs, or 0444
* for world-readable, 0644 for root-writable, etc. Note that if it
* is writable, you may need to use kernel_param_lock() around
* accesses (esp. charp, which can be kfreed when it changes).
*
* The @type is simply pasted to refer to a param_ops_##type and a
* param_check_##type: for convenience many standard types are provided but
* you can create your own by defining those variables.
*
* Standard types are:
* byte, short, ushort, int, uint, long, ulong
* charp: a character pointer
* bool: a bool, values 0/1, y/n, Y/N.
* invbool: the above, only sense-reversed (N = true).
*/
#define module_param(name, type, perm) \
module_param_named(name, name, type, perm)
/**
* module_param_named - typesafe helper for a renamed module/cmdline parameter
* @name: a valid C identifier which is the parameter name.
* @value: the actual lvalue to alter.
* @type: the type of the parameter
* @perm: visibility in sysfs.
*
* Usually it's a good idea to have variable names and user-exposed names the
* same, but that's harder if the variable must be non-static or is inside a
* structure. This allows exposure under a different name.
*/
#define module_param_named(name, value, type, perm) \
param_check_##type(name, &(value)); \
module_param_cb(name, ¶m_ops_##type, &value, perm); \
__MODULE_PARM_TYPE(name, #type)
name既是用户看到的参数名,又是模块内接受参数的变量;
type指定参数类型.
perm指定了在sysfs中相应文件的访问权限。访问权限与linux文件爱你访问权限相同的方式管理,如0644,或使用stat.h中的宏如S_IRUGO表示。
0表示完全关闭在sysfs中相对应的项。
3. 完整测试例程如下:
/*
* a simple kernel module: hello
*
* Copyright (C) 2020
*
* Licensed under GPLv2 or later
*/
#include <linux/init.h>
#include <linux/module.h>
#define MY_MAJOR 0x09
static int global_val_test = MY_MAJOR;
module_param(global_val_test, int, 0644);
static int __init hello_init(void)
{
printk(KERN_INFO "global_val_test = %d\n", global_val_test);
if (global_val_test == 9)
printk(KERN_INFO "hello my world enter\n");
else
printk(KERN_INFO "hello world enter\n");
return 0;
}
module_init(hello_init);
static void __exit hello_exit(void)
{
printk(KERN_INFO "hello World exit\n");
}
module_exit(hello_exit);
MODULE_AUTHOR("xxxx <xxxx>");
MODULE_LICENSE("GPS v2"); //模块许可证声明,一般用GPL v2
MODULE_VERSION("1.0.0");
MODULE_DESCRIPTION("A simple hello world module");
MODULE_ALIAS("a simplest module"); //别名
Makefile如下:
KVERS = $(shell uname -r)
obj-m := first_hello.o
first_hello-objs := hello.o
build: kernel_modules
kernel_modules:
make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
clean:
make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean
编译方法:make
加载模块:insmod first_hello.ko global_val_test=5
查看log方法:tail /var/log/messages
或者可以通过:cat /sys/module/first_hello/parameters/global_val_test 查看参数的值.
完整源码见: