3、Linux驱动开发:模块_传递参数

这篇具有很好参考价值的文章主要介绍了3、Linux驱动开发:模块_传递参数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

🍅点击这里查看所有博文

  随着自己工作的进行,接触到的技术栈也越来越多。给我一个很直观的感受就是,某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了,只有经常会用到的东西才有可能真正记下来。存在很多在特殊情况下有一点用处的技巧,用的不多的技巧可能一个星期就忘了。

  想了很久想通过一些手段把这些事情记录下来。也尝试过在书上记笔记,这也只是一时的,书不在手边的时候那些笔记就和没记一样,不是很方便。

  很多时候我们遇到了问题,一般情况下都是选择在搜索引擎检索相关内容,这样来的也更快一点,除非真的找不到才会去选择翻书。后来就想到了写博客,博客作为自己的一个笔记平台倒是挺合适的。随时可以查阅,不用随身携带。

  同时由于写博客是对外的,既然是对外的就不能随便写,任何人都可以看到。经验对于我来说那就只是经验而已,公布出来说不一定我的一些经验可以帮助到其他的人。遇到和我相同问题时可以少走一些弯路。

  既然决定了要写博客,那就只能认真去写。不管写的好不好,尽力就行。千里之行始于足下,一步一个脚印,慢慢来 ,写的多了慢慢也会变好的。权当是记录自己的成长的一个过程,等到以后再往回看时,就会发现自己以前原来这么菜😂。

  本系列博客所述资料均来自互联网资料,并不是本人原创(只有博客是自己写的)。出于热心,本人将自己的所学笔记整理并推出相对应的使用教程,方面其他人学习。为国内的物联网事业发展尽自己的一份绵薄之力,没有为自己谋取私利的想法。若出现侵权现象,请告知本人,本人会立即停止更新,并删除相应的文章和代码。

前言

  在用户态下编程可以通过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 <linux/init.h>
#include <linux/module.h>
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

补充说明

模块信息查询(modinfo)

  源文件中记录的额外信息,都会在编译后被打包到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)

mask权限问题

  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

  那么本篇博客就到此结束了,这里只是记录了一些我个人的学习笔记,其中存在大量我自己的理解。文中所述不一定是完全正确的,可能有的地方我自己也理解错了。如果有些错的地方,欢迎大家批评指正。如有问题直接在对应的博客评论区指出即可,不需要私聊我。我们交流的内容留下来也有助于其他人查看,说不一定也有其他人遇到了同样的问题呢😂。文章来源地址https://www.toymoban.com/news/detail-610852.html

到了这里,关于3、Linux驱动开发:模块_传递参数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 嵌入式linux驱动开发之移远4G模块EC800驱动移植指南

    回顾下移远4G模块移植过程, 还是蛮简单的。一通百通,无论是其他4G模块都是一样的。这里记录下过程,分享给有需要的人。环境使用正点原子的imax6ul开发板,板子默认支持中兴和移远EC20的驱动,这里要移植使用的是移远4G模块EC800。 imax6ul开发板 虚拟机(Ubuntu18.04) 交叉编译

    2024年02月17日
    浏览(71)
  • 嵌入式linux之iMX6ULL驱动开发 | 移远4G模块EC800驱动移植指南

    回顾下移远4G模块移植过程, 还是蛮简单的。一通百通,无论是其他4G模块都是一样的。这里记录下过程,分享给有需要的人。环境使用正点原子的imax6ul开发板,板子默认支持中兴和移远EC20的驱动,这里要移植使用的是移远4G模块EC800。 imax6ul开发板 虚拟机(Ubuntu18.04) 交叉编译

    2024年02月12日
    浏览(61)
  • 【Linux Shell】3. 传递参数

    在执行 Shell 脚本时,可以向脚本传递参数, 脚本内获取参数的格式为 $n,n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,依此类推。 实例:向脚本传递三个参数,并分别输出,其中 $0 为执行的文件名(包含文件路径)。 为脚本设置可执行权限,

    2024年01月24日
    浏览(35)
  • Linux【脚本 04】Shell脚本传递参数的4种方式(位置参数、特殊变量、环境变量和命名参数)实例说明

    Shell脚本是一种命令语言,可以用于自动化执行各种任务。在脚本中,我们可以通过参数来传递信息,这样脚本就可以根据这些信息来执行特定的操作。本文将介绍如何在shell脚本中传递参数,包括位置参数、特殊变量、环境变量和命名参数。 1.1 解释器 #!/bin/bash 称为shebang或

    2024年02月06日
    浏览(85)
  • Linux驱动3:驱动模块加载与卸载

    目录 一、环境配置  1、开发板环境 2、uboot环境 ①设置bootargs ②设置bootcmd 二、加载驱动与卸载驱动  1、加载命令选择 2、创建目录环境以及驱动文件复制 3、加载驱动  提示①“modprobe: can\\\'t open \\\'modules.dep\\\': No such file or directory”  提示②module license \\\'unspecified\\\' 4、卸载驱动 提示

    2024年02月05日
    浏览(58)
  • Linux中驱动模块加载方法分析

    如何管理驱动模块 由于Linux驱动模块众多,系统对模块加载顺序有要求,一些基础模块在系统启动时需要很早就被加载;开发者加入自己的模块时,需要维护一个模块初始化列表,上面两方面的做起来很困难,为了科学地管理这些模块,首先要解决两个问题: 如何方便开发者

    2024年02月12日
    浏览(39)
  • 【Linux驱动】内核模块编译 —— make modules 的使用(单模块编译、多模块编译)

    编译驱动一般采用的是将驱动编译成模块(.ko 文件),然后加载到内核,这其中就用到了 make modules 命令。 目录 一、单模块编译 1、一个 c 文件编译成一个 ko 文件 2、多个文件编译成一个 ko 文件 二、多模块编译(多文件多模块) 下面是最简易的单文件单模块编译,假设我们

    2024年02月10日
    浏览(66)
  • Verilog HDL中模块参数传递的方法

    “parameter”是Verilog HDL中的一个,代表着参数型常量,即用parameter来定义一个标识符代表一个常量,这样可以提高程序的可读性与可维护性。 例如: parameter max_time = 10; //定义参数max_time为常量10 参数型常量在Verilog HDL中通常用来定义时间延迟和数据位宽。 一方面,对于

    2024年02月11日
    浏览(40)
  • 修改linux的/sys目录下内核参数、模块...

    ① /sys/devices 该目录下是全局设备结构体系,包含所有被发现的注册在各种总线上的各种物理设备。一般来说,所有的物理设备都按其在总线上的拓扑结构来显示,但有两个例外,即platform devices和system devices。platform devices一般是挂在芯片内部的高速或者低速总线上的各种控制

    2024年02月05日
    浏览(65)
  • Linux GPIO模块-RK3588 GPIO驱动分析

    GPIO是可编程的通用I/O外设。如下图所示,RK3588 GPIO控制器包含3个部分;APB接口模块和SoC内部的APB总线连接,负责与SoC交换数据,位宽为32位;I/O port接口模块管理外部的引脚,引脚的输入和输出都要经过该模块;中断探测模块负责GPIO控制器的中断上报与处理。 RK3588 GPIO控制器

    2023年04月15日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包