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 查看參數的值.
完整源碼見: