您的位置:首页 > 其它

内核之旅 --- 内核模块学习1---内核模块参数传递

2015-09-12 10:32 295 查看
内核模块的参数传递:

内核模块在加载时是可以添加参数的,但是支持类型有所改变。

首先,内核模块中的变量如果需要使用外界传递的参数需要使用特定的宏

module_param(member,type,perm)

这三个参数分别表示:

member: 变量名

type : 类型名

perm : 入口项的访问许可源码。

<span style="font-size:18px;">static char *whom = "world";
static int  howmany = 1;
module_param(howmany,int,S_IRUGO);
module_param(whom,charp,S_IRUGO);</span>


只有使用这个宏才能使我们驱动里边的参数接受到外面的值。

内核支持的模块参数类型有下面几种:

bool :布尔值(取ture 或 false ),关联的变量应该是int型。

invbool: 类型反转其值,也就是说,ture 值变成false , 而false 变成 ture.

charp:字符指针值。内核会为用户提供的字符串分配内存,并相应设置指针。

int ,long , short ,uint ,ulong ,ushort 具有不同长度的基本整数值,以U开头就是无符号值。

也可以接受数组,需要使用宏:

module_param_array(name,type,num,perm);

其中name 就是数组名,type 是数组的元素类型,num 是一个整数变量就是数组元素的个数,越界值直接报错。详情参见moduleparam.h .

这个文件在源码包/include/linux/moduleparam.h

我们可以尝试分析一下,追踪一下这个源码:

/**
* module_param_array - a parameter which is an array of some type
* @name: the name of the array variable
* @type: the type, as per module_param()
* @nump: optional pointer filled in with the number written
* @perm: visibility in sysfs
*
* Input and output are as comma-separated values.  Commas inside values
* don't work properly (eg. an array of charp).
*
* ARRAY_SIZE(@name) is used to determine the number of elements in the
* array, so the definition must be visible.
*/
#define module_param_array(name, type, nump, perm)		\
module_param_array_named(name, name, type, nump, perm)


可以看到这就是数组分配宏的源码,它调用的是

module_param_array_named(name,name,type,nump,perm)

那好,我们再追踪这个宏看看

/**
* module_param_array_named - renamed parameter which is an array of some type
* @name: a valid C identifier which is the parameter name
* @array: the name of the array variable
* @type: the type, as per module_param()
* @nump: optional pointer filled in with the number written
* @perm: visibility in sysfs
*
* This exposes a different name than the actual variable name.  See
* module_param_named() for why this might be necessary.
*/
#define module_param_array_named(name, array, type, nump, perm)		\
param_check_##type(name, &(array)[0]);				\
static const struct kparam_array __param_arr_##name		\
= { .max = ARRAY_SIZE(array), .num = nump,                      \
.ops = ¶m_ops_##type,					\
.elemsize = sizeof(array[0]), .elem = array };		\
__module_param_call(MODULE_PARAM_PREFIX, name,			\
¶m_array_ops,				\
.arr = &__param_arr_##name,			\
perm, -1, 0);				\
__MODULE_PARM_TYPE(name, "array of " #type)


英语真麻烦。。。。算了还是翻译给大家看看吧。

第一行:重命名数组的参数

@name:一个有效的C表示符作为参数的名字

@array:数组明变量

@type:类型

@nump:数组长度

@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)
param_check_##type(name,&(value));

就是检查这个类型是否有效,“##” 是C中的宏替换运算符,他接受一个名字,和长度。安全检查。

module_param_cd(name,¶m_ops_##type,&value,perm)

这个宏调用的是__module_param_call

/* This is the fundamental function for registering boot/module
parameters. */
#define __module_param_call(prefix, name, ops, arg, perm, level, flags)	\
/* Default value instead of permissions? */			\
static const char __param_str_##name[] = prefix #name; \
static struct kernel_param __moduleparam_const __param_##name	\
__used								\
__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
= { __param_str_##name, ops, VERIFY_OCTAL_PERMISSIONS(perm),	\
level, flags, { arg } }
这个函数在模块中注册一个变量。

回到上边这个宏,我们看到再次确定了变量名与类型的匹配

__MODULE_PARM_TYPE(name, #type)


然后这个数组就算是定义成功,当使用时,内核会让加载器给它分配相应内存。其实这些宏的工作仅仅是检查参数,保存参数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: