点击这里查看所有博文
随着自己工作的进行,接触到的技术栈也越来越多。给我一个很直观的感受就是,某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了,只有经常会用到的东西才有可能真正记下来。存在很多在特殊情况下有一点用处的技巧,用的不多的技巧可能一个星期就忘了。
想了很久想通过一些手段把这些事情记录下来。也尝试过在书上记笔记,这也只是一时的,书不在手边的时候那些笔记就和没记一样,不是很方便。
很多时候我们遇到了问题,一般情况下都是选择在搜索引擎检索相关内容,这样来的也更快一点,除非真的找不到才会去选择翻书。后来就想到了写博客,博客作为自己的一个笔记平台倒是挺合适的。随时可以查阅,不用随身携带。
同时由于写博客是对外的,既然是对外的就不能随便写,任何人都可以看到。经验对于我来说那就只是经验而已,公布出来说不一定我的一些经验可以帮助到其他的人。遇到和我相同问题时可以少走一些弯路。
既然决定了要写博客,那就只能认真去写。不管写的好不好,尽力就行。千里之行始于足下,一步一个脚印,慢慢来
,写的多了慢慢也会变好的。权当是记录自己的成长的一个过程,等到以后再往回看时,就会发现自己以前原来这么菜。
本系列博客所述资料均来自互联网资料
,并不是本人原创(只有博客是自己写的)。出于热心,本人将自己的所学笔记整理并推出相对应的使用教程,方面其他人学习。为国内的物联网事业发展尽自己的一份绵薄之力,没有为自己谋取私利的想法
。若出现侵权现象,请告知本人,本人会立即停止更新,并删除相应的文章和代码。
在用户态下编程可以通过main来传递命令行参数,而编写一个内核模块则可通过module_param来传递命令行参数。
module_param宏是Linux 2.6内核中新增的,该宏被定义在include/linux/moduleparam.h
文件中,具体定义如下:
/**
* 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使用了3个参数:变量名,它的类型,以及一个权限掩码用来做一个辅助的sysfs入口。这个宏定义应当放在函数之外,典型的是出现在源文件的前面。
module_param_named则是另一个变种,以示例说明可使得var变量在内核外的变量名称为var_out。在内核外给var_out赋值等同于给模块内var变量赋值。
static char *whom = "hello \n";
static int var = 1;
module_param(whom,charp,0644);
module_param_named(var_out,var,int,0644);
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("PD");
static char *whom = "hello";
static int var = 1;
module_param(whom,charp,0644);
module_param_named(var_out,var,int,0644);
static int hello_init(void)
{
printk("hello_init %s \n",whom);
printk("hello_init %d\n",var);
return 0;
}
static void hello_exit(void)
{
printk("hello_exit %s \n",whom);
printk("hello_exit %d\n",var);
return;
}
module_init(hello_init);
module_exit(hello_exit);
insmod加载模块时,可直接携带对应的参数。当传入不存在的参数时,会报错unknown parameter
。
root@ubuntu:# insmod ./hello.ko var=100 var_out=200 whom="test"
root@ubuntu:# rmmod ./hello.ko
root@ubuntu:# dmesg
[ 9730.375507] hello: unknown parameter 'var' ignored
[ 9730.375536] hello_init test
[ 9730.375537] hello_init 200
[ 9733.244654] hello_exit test
[ 9733.244655] hello_exit 200
如不携带参数,则使用模块的默认值。
root@ubuntu:# insmod ./hello.ko
root@ubuntu:# rmmod ./hello.ko
root@ubuntu:# dmesg
[ 9520.771593] hello_init hello
[ 9520.771594] hello_init 1
[ 9534.227683] hello_exit hello
[ 9534.227684] hello_exit 1
sysfs: 内核会给一些重要的资源创建专属目录或者文件。每个模块会在/sys/module下创建一个同名的文件夹。
文件夹在加载时被创建,卸载后立即被销毁。
root@ubuntu:# insmod ./hello.ko var=100 var_out=200 whom="test"
root@ubuntu:# ls /sys/module/hello
coresize holders initsize initstate notes parameters refcnt sections srcversion taint uevent
root@ubuntu:# rmmod ./hello.ko
root@ubuntu:# ls /sys/module/hello
ls: cannot access '/sys/module/hello': No such file or directory
在专属目录下的parameters目录中记录了模块参数的外部节点。均是虚拟字符设备,可直接通过控制台echo修改,cat读取。
root@ubuntu:# /sys/module/hello# cat ./parameters/var_out
200
root@ubuntu:# /sys/module/hello# cat ./parameters/whom
test
root@ubuntu:# /sys/module/hello# echo 300 > ./parameters/var_out
root@ubuntu:# /sys/module/hello# echo "hahahaha" > ./parameters/whom
root@ubuntu:# /sys/module/hello# cat ./parameters/var_out
300
root@ubuntu:# /sys/module/hello# cat ./parameters/whom
hahahaha
上述修改立即生效,在模块退出时查看日志,可知变量值已经被修改。
root@ubuntu:# dmesg
[10522.899811] hello: unknown parameter 'var' ignored
[10522.899837] hello_init test
[10522.899838] hello_init 200
[10572.883954] hello_exit hahahaha
[10572.883955] hello_exit 300
源文件中记录的额外信息,都会在编译后被打包到ko文件中,以下示例中仅列出一部分。
MODULE_LICENSE("GPL");
MODULE_AUTHOR("PD");
MODULE_DESCRIPTION("3_param example");
MODULE_ALIAS("example3");
MODULE_PARM_DESC(var,"Boolean to enable debugging (0/1 == off/on)");
在shell中可通过modinfo查询模块的全部信息。
root@ubuntu:# modinfo ./hello.ko
filename: ./hello.ko
alias: example3
description: 3_param example
author: PD
license: GPL
srcversion: 6D5DF27C63EBFF621C183E3
depends:
retpoline: Y
name: hello
vermagic: 4.15.0-142-generic SMP mod_unload
parm: whom:charp
parm: var_out:int
parm: var:Boolean to enable debugging (0/1 == off/on)
parameters中的对外参数所持有的权限,与代码中module_param注册时填写的权限一致。
module_param(whom,charp,0644);
module_param_named(var_out,var,int,0644);
root@ubuntu:# ll /sys/module/hello/parameters/
total 0
drwxr-xr-x 2 root root 0 Jul 22 03:59 ./
drwxr-xr-x 6 root root 0 Jul 22 03:58 ../
-rw-r--r-- 1 root root 4096 Jul 22 03:59 var_out
-rw-r--r-- 1 root root 4096 Jul 22 03:59 whom
该权限不能超过module_param_call的mask最大权限,若填写的权限比mask大,则最终效果是以mask为准。对外的现象就是设置的权限不起作用。
/* This is the fundamental function for registering boot/module
parameters. */
#define __module_param_call(prefix, name, ops, arg, perm, level) \
/* Default value instead of permissions? */ \
static int __param_perm_check_##name __attribute__((unused)) = \
BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \
+ BUILD_BUG_ON_ZERO(sizeof(""prefix) > MAX_PARAM_PREFIX_LEN); \
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, perm, level, { arg } }
本例中参数声明时指定权限为0666,结果实际加载后参数文件的权限还是0644。
module_param(whom,charp,0666);
module_param_named(var_out,var,int,0666);
root@ubuntu:# ll /sys/module/hello/parameters/
total 0
drwxr-xr-x 2 root root 0 Jul 22 03:59 ./
drwxr-xr-x 6 root root 0 Jul 22 03:58 ../
-rw-r--r-- 1 root root 4096 Jul 22 03:59 var_out
-rw-r--r-- 1 root root 4096 Jul 22 03:59 whom
那么本篇博客就到此结束了,这里只是记录了一些我个人的学习笔记,其中存在大量我自己的理解。文中所述不一定是完全正确的,可能有的地方我自己也理解错了。如果有些错的地方,欢迎大家批评指正。如有问题直接在对应的博客评论区指出即可,不需要私聊我。我们交流的内容留下来也有助于其他人查看,说不一定也有其他人遇到了同样的问题呢。