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

来源:互联网 发布:网络用语打call的意思 编辑:程序博客网 时间:2024/06/07 07:46

 内核模块的参数传递:

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

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

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 = &param_ops_##type,\    .elemsize = sizeof(array[0]), .elem = array };\__module_param_call(MODULE_PARAM_PREFIX, name,\    &param_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, &param_ops_##type, &value, perm);   \__MODULE_PARM_TYPE(name, #type)
param_check_##type(name,&(value));

就是检查这个类型是否有效,“##” 是C中的宏替换运算符,他接受一个名字,和长度。安全检查。
module_param_cd(name,&param_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)

然后这个数组就算是定义成功,当使用时,内核会让加载器给它分配相应内存。其实这些宏的工作仅仅是检查参数,保存参数。





0 0