内核参数module_param的有关操作

内核参数module_param的有关操作

定义一个内核参数比较简单

module_param(参数变量名字,类型,访问权限)

MODULE_PARM_DESC(参数变量名字,“参数说明描述”)

如果需要限制或者检查用户输入的参数的值,比如说限制输入的整型数是 256~512的某个范围等等,输入的一定是某个特定字符串等。那么可以用这个宏。这个支持你传进去一个参数处理的回调函数。

module_param_call 2.6.35 以下

module_param_cb 2.6.38 

这里我只针对module_param_cb 做一下说明,module_param_call 用法类似,看内核中的定义:

/**
 * module_param_cb - general callback for a module/cmdline parameter
 * @name: a valid C identifier which is the parameter name.
 * @ops: the set & get operations for this parameter.
 * @perm: visibility in sysfs.
 *
 * The ops can have NULL set or get functions.
 */
#define module_param_cb(name, ops, arg, perm)				      \
	__module_param_call(MODULE_PARAM_PREFIX,			      \
			    name, ops, arg, __same_type((arg), bool *), perm)

1、name是你要定义的变量的名字

2、ops中指定你要用于set和get这个变量value的方法

3、arg是你在你的code中默认初始化的这个变量名

4、perm是系统读写等权限的设置

看一个实例你就全明白了

static int set_enabled(const char *val, const struct kernel_param *kp)
{
	int rv = param_set_bool(val, kp);

	if (rv)
		return rv;

	if (otgwl_xceiv)
		otgwl_handle_event(otgwl_xceiv->last_event);

	return 0;
}

static struct kernel_param_ops enabled_param_ops = {
	.set = set_enabled,
	.get = param_get_bool,
};

module_param_cb(enabled, &enabled_param_ops, &enabled, 0644);
MODULE_PARM_DESC(enabled, "enable wakelock when VBUS present");
我也懒得自己去写code 了,这是内核中的code,也许更有说服力,这个code的路径,感兴趣可以自己去看看:kernel/drivers/usb/otg/otg-wakelock.c

这样一来,这段code会在开发板的sys/module/otg_wakelock/parameters/目录下创建一个名字叫enable的文件,你可以通过这个文件set和get变量enable的数据

read value:cat enable

write value:echo 1 > enable

当你read value的时候,上面ops中定义的方法param_get_bool会被调用,这是内核已经实现的方法,直接get bool,这里我们希望enable是一个bool类型,如果是int类型那么就是get int方法了

同样的,当你write value时,set_enabled这个自己实现的方法会被调用,这里只是进行了简单的检查

其实有些时候你完全可以没有必要这么麻烦,为什么这么说呢??

我们就一点点来看一下,其实内核中module_param可以实现我们上面说的所有这一些功能,这个方法不光可以创建一个指定类型的变量的文件,同时还提供了系统默认的get和set的方法,没有必要我们自己去实现

看看module_param的定义:

/**
 * module_param - typesafe helper for a module/cmdline parameter
 * @value: the variable to alter, and exposed parameter name.
 * @type: the type of the parameter
 * @perm: visibility in sysfs.
 *
 * @value 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 kparam_block_sysfs_write() 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这个方法

/**
 * 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)

这个方法的实现是最关键的地方,我们仔细看一下他都做了些什么事情,这里为了方便分析,假定我们的变量type类型是int

1、调用param_check_##type方法,##用于连接两个字符,我在我的C语言每天一小步专栏中说到这个问题,大家可以参考:http://blog.csdn.net/xinyuwuxian/article/details/9033627

这里也就是执行param_check_int,检查变量是不是int 类型

2、调用module_param_cb,这里大家应该熟悉了,上面我们已经说的很清楚这个方法了,这不过这里的ops是系统的ops,针对int类型就是param_ops_int

3、最后调用__MODULE_PARM_TYPE方法指定我们的type也就是int,#的用法在我上面提到的专栏文章中也已经说到

这样一来,可以很清楚的理解了,不过需要注意的是module_param_cb这个方法有时还是不可或缺的,就像上面我们不只是要进行参数检查,我们还想加入我们自己的功能,所以这时我们需要自己实现我们的set或者get方法,这个时候module_param_cb就是谁也替代不了的了,这就是天生我材必有用,O(∩_∩)O~

就到这了,O(∩_∩)O~

你可能感兴趣的:(Linux,Driver)