module_param()理解
-------------------------------------------
在用户态下编程可以通过main()的来传递命令行参数,而编写一个内核模块则通过module_param()
module_param()宏是Linux 2.6内核中新增的,该宏被定义在include/linux/moduleparam.h文件中,具体定义如下:
#define module_param(name, type, perm)
module_param_named(name, name, type, perm)
其中使用了 3 个参数:要传递的参数变量名, 变量的数据类型, 以及访问参数的权限。
perm参数的作用是什么?
-------------------------------------------
perm参数是一个权限值,表示此参数在sysfs文件系统中所对应的文件节点的属性。你应当使用 <linux/stat.h> 中定义的值. 这个值控制谁可以存取这些模块参数在sysfs中的表示.当perm为0时,表示此参数不存在sysfs文件系统下对应的文件节点。 否则, 模块被加载后,在/sys/module/目录下将出现以此模块名命名的目录, 带有给定的权限.。
权限在include/linux/stat.h中有定义
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010
#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001
使用S_IRUGO作为参数可以被所有人读取, 但是不能改变; S_IRUGO|S_IWUSR允许root来改变参数. 注意, 如果一个参数被sysfs修改, 你的模块看到的参数值也改变了, 但是你的模块没有任何其他的通知. 你应当不要使模块参数可写, 除非你准备好检测这个改变并且因而作出反应.
module_param()应当放在任何函数之外, 典型地是出现在源文件的前面.定义如:
static char *whom = "world";
static int howmany = 1;
module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO);
模块参数支持许多类型:
bool 一个布尔型(true或者false)值(相关的变量应当是int类型).
invbool invbool类型颠倒了值, 所以真值变成 false, 反之亦然.
charp 一个字符指针值. 内存为用户提供的字串分配, 指针因此设置.
int
long
short
uint
ulong
ushort
数组参数, 用逗号间隔的列表提供的值, 模块加载者也支持. 声明一个数组参数, 使用:
module_param_array(name, type, num, perm);
name 数组的名子(也是参数名),
type 数组元素的类型,
num 一个整型变量,
perm 通常的权限值.
如果数组参数在加载时设置, num被设置成提供的数的个数. 模块加载者拒绝比数组能放下的多的值.
hello.c
-------------------------------------------
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
MODULE_LICENSE ("Dual BSD/GPL");
static char *who = "world";
static int times = 1;
module_param (times, int, S_IRUSR);
module_param (who, charp, S_IRUSR);
static int hello_init (void)
{
int i;
for (i = 0; i < times; i++)
printk (KERN_ALERT "(%d) hello, %s!\n", i, who);
return 0;
}
static void hello_exit (void)
{
printk (KERN_ALERT "Goodbye, %s!\n", who);
}
module_init (hello_init);
module_exit (hello_exit);
编译生成可执行文件hello
# insmod hello who="world" times=5
#(1) hello, world!
#(2) hello, world!
#(3) hello, world!
#(4) hello, world!
#(5) hello, world!
# rmmod hello
# Goodbye,world!
注: 如果加载模块hello时,没有输入任何参数,那么who的初始值为"world",times的初始值为1
给模块传递参数 日月 发表于 - 2010-1-20 7:38:00
3 推荐
|
Linux内核模块参数权限 (2010-03-03 18:21) 分类: kernel
在进行linux内核模块编程时,常常需要给模块传递参数,其作用是从使用的设备号到驱动应当任何操作的几个方面. 例如, SCSI 适配器的驱动常常有选项控制标记命令队列的使用, IDE 驱动允许用户控制 DMA 操作. 如果你的驱动控制老的硬件, 还需要被明确告知哪里去找硬件的 I/O 端口或者 I/O 内存地址. 内核通过在加载驱动的模块时指定可变参数的值, 支持这些要求。
参数常常被声明为一个静态全局变量,如static int num=10;然后使用module_param(参数名,参数类型,参数读写权限)为模块定义一个参数,例如:
module_prarm(num,int,S_IRUGO);
这样你就可以在insmod(装载模块)的时候为参数指定值,如果没有指定则使用默认值,例如上面的num=10,则10是参数num的默认值。下面以一个例子说明:
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int num=10;
module_param(num,int,S_IRUGO);
static int hello_init(void)
{
printk("Hello module init.\n");
printk("num=%d\n",num);
return 0;
}
static void hello_exit(void)
{
printk("Goodbye module exit.\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_DESCRIPTION("a simple module");
MODULE_ALIAS("hello");
将以上代码保存为文件hello.c,编写Makefile文件对其进行编译:
# Makefile2.6
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
else
PWD := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD)
endif
然后make就可以了,make会生成:
|-- Module.symvers
|-- built-in.o
|-- hello.ko
|-- hello.mod.c
|-- hello.mod.o
`-- hello.o
这些文件,其中的hello.ko就是编译生成的模块,使用insmod将hello.ko模块装载进内核,这个需要超级用户权限,我的系统是ubuntu7.10,所以使用如下命令装载:
sudo insmod hello.ko num=20
使用dmesg命令查看运行结果:
[email protected]:~/module$ dmesg #实际上是读取/var/log/messages文件的内容
... #省略以前的信息
[14801.675260] Hello module init.
[14801.675265] num=20
这就是运行结果。如果你插入的是sudo insmod hello.ko,那么:
使用dmesg命令查看运行结果:
[email protected]:~/module$ dmesg #实际上是读取/var/log/messages文件的内容
... #省略以前的信息
[14801.675260] Hello module init.
[14801.675265] num=10 #取默认值
以上是内核模块的编译和运行情况,实际上你还需要用到lsmod(查看模块是否被插入,一般在打印出来的第一行里)、rmmod(卸载装载的模块,只有当模块的引用计数为0时才能被卸载)等命令。
那么实质上当你装载模块hello.ko时,系统会在/sys/module下生成一个hello文件夹:
[email protected]:/sys/module/hello$ tree
.
|-- holders
|-- initstate
|-- parameters
| `-- num
|-- refcnt
|-- sections
| |-- __param
| `-- __versions
`-- srcversion
3 directories, 6 files
其中parameters目录中就存放的是该模块的参数,一个参数对应一个文件,文件的内容为参数的默认值例如:
[email protected]:/sys/module/hello/parameters$ tree
.
`-- num
0 directories, 1 file
xiy[email protected]:/sys/module/hello/parameters$ cat num
10
在module_param(num,int,S_IRUGO);
定义参数时,其中的参数读写权限S_IRUGO其实是对参数文件的读写权限,所以权限的设置值就和对文件的设置值一样,例如上面对num参数权限的设置S_IRUGO就是对所有用户具有读的权限,而S_IRUGO|S_IWUSR 则允许 root 来改变参数。