2014年(84)
分类: LINUX
2014-05-15 16:01:25
原文地址:内核基础架构---模块参数 作者:linuxDOS
#########
insmod net_dev.ko param_queue_id=${QUEUE_ID} param_board=$BOARD \
param_tcont_id=$TCONT_ID
param_us_gem_flow_id=$US_GEMFLOW_ID
static int param_queue_id =3;
module_param(param_queue_id, int, 0);
int map_ds_traffic_to_cpu = 0;
module_param(map_ds_traffic_to_cpu, int,
0);
//
参数用 module_param 宏定义来声明, 它定义在 moduleparam.h.
module_param(name,type,perm);
module_param 使用了 3 个参数: 变量名, 它的类型, 以及一个权限掩码用来做一个辅助的 sysfs 入口(查看/sys/module/xXX/会发现里面有我们对应的参数,当然必须有至少读的权限,默认0,为任何人都没有权限,甚至不可见). 这个宏定义应当放在任何函数之外, 典型地是出现在源文件的前面.
数组参数, 用逗号间隔的列表提供的值, 模块加载者也支持. 声明一个数组参数, 使用:
module_param_array(name,type,num,perm);
这里 name 是你的数组的名称(也是参数名),
type 是数组元素的类型,
num 是一个整型变量,
perm 是通常的权限值.
如果数组参数在加载时设置, num 被设置成提供的数的个数. 模块加载者拒绝比数组能放下的多的值. module_param_array() 宏的第三个参数用来记录用户insmod 时提供的给这个数组的元素个数,NULL 表示不关心用户提供的个数
如果模块参数是一个字符串时,通常使用charp类型定义这个模块参数。内核复制用户提供的字符串到内存,并且相对应的变量指向这个字符串。
例如:
另一种方法是通过宏module_param_string()让内核把字符串直接复制到程序中的字符数组内。
这里,name是外部的参数名,string是内部的变量名,len是以string命名的buffer大小(可以小于buffer的大小,但是没有意义),perm表示sysfs的访问权限(或者perm是零,表示完全关闭相对应的sysfs项)。
例如:
如果需要传递多个参数可以通过宏module_param_array()实现。
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开
modinfo [-adhpv][模块文件]
功能:显示kernel模块的信息。
参数:
-d或--description 显示模块的说明。
引导期间内核选项 __setup
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开
点击(此处)折叠或打开
真正代码层:
static char param_board[20]="";
module_param_string(param_board, param_board, sizeof(param_board), 0);
static char *name;
module_param(name, charp, 0);
module_param_string(name, string, len, perm);
static char species[BUF_LEN];
module_param_string(specifies, species, BUF_LEN, 0);
module_param_array(name, type, nump, perm);
其中,name既是外部模块的参数名又是程序内部的变量名,type是数据类型,perm是sysfs的访问权限。指针nump指向一个整数,其值表示有多少个参数存放在数组name中。值得注意是name数组必须静态分配.
说了这么多,来让我们看看它的本质吧.
include/linux/moduleparam.h
那么我们看下 struct kernel_param:
查看模块信息:
-a或--author 显示模块开发人员。
-h或--help 显示modinfo的参数使用方法。
-p或--parameters 显示模块所支持的参数。
-V或--version 显示版本信息。
既然上面说到了模块参数,这里顺便也说下
用__setup宏注册关键字
net/core/dev.c 比较常见的netdev关键字 ,在系统启动时候的参数
我们看看它是如何调用的.
在init/main.c 中
asmlinkage void __init start_kernel(void)
{
...
printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
parse_early_param();
parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
&unknown_bootoption);
...
}
注册的时候有两个宏,__setup, early_param 当然既然带个early自然会比__setup注册的处理的早. 也就是我们看到start_kernel里两个函数的先后顺序.
我们就把宏展开:
本质是注册了struct obs_kernel_param 并把它放到了内存节区 .init.setup ,关于内存节区前面我们讲过。当然如果注册的关键字被编译成模块,那么这个宏扩展为空.
我们先看early解析:
那么正常注册的关键字呢?
include/asm-generic/vmlinux-lds.h :
这里查询__param ,如果找到赋值并返回.