当前位置: 首页 > news >正文

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/moduleparameters. */
#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

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

相关文章:

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

目录 &#x1f345;点击这里查看所有博文 随着自己工作的进行&#xff0c;接触到的技术栈也越来越多。给我一个很直观的感受就是&#xff0c;某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了&#xff0c;只有经常会用到的东西才有可能真正记…...

基于 ThinkPHP 5.1(稳定版本) 开发wms 进销存系统源码

基于ThinkPHP 5.1&#xff08;LTS版本&#xff09;开发的WMS进销存系统源码 管理员账号密码&#xff1a;admin 一、项目简介 这个系统是一个基于ThinkPHP框架的WMS进销存系统。 二、实现功能 控制台 – 权限管理&#xff08;用户管理、角色管理、节点管理&#xff09; – 订…...

全面解析 SOCKS5 代理和 HTTP 代理在网络安全与爬虫应用中的技术对比与应用指南

一、SOCKS5 代理和 HTTP 代理的基本原理 SOCKS5 代理&#xff1a;SOCKS5 是一种网络协议&#xff0c;可以在传输层代理 TCP 和 UDP 请求。它不解析请求内容&#xff0c;仅在客户端和代理服务器之间建立连接&#xff0c;并转发数据。SOCKS5 代理支持众多网络协议和端口类型&…...

DevOps系列文章 之 docker 制作kafka镜像

Docker制作Kafka镜像教程 概述 本教程将指导你如何使用Docker制作一个Kafka镜像。Kafka是一个高性能、分布式的消息队列系统&#xff0c;用于处理大规模的实时数据流。使用Docker制作Kafka镜像可以方便地部署和管理Kafka集群。 整体流程 下面是制作Kafka镜像的整体流程&#xf…...

iPhone 安装 iOS 17公测版(Public Beta)

文章目录 步骤1. 备份iPhone资料步骤2. 申请iOS 17 公测Beta 资格步骤3. 下载iOS 16 Beta 公测描述档步骤4. 选择iOS 17 Beta 公测描述档更新项目步骤5. 升级iOS 17 Public Beta 公开测试版 苹果已经开始向大众释出首个iOS 17 公开测试版/ 公测版( iOS 17 Public Beta)&#xf…...

Spingboot yaml 配置文件及数据读取

属性配置在这里插入图片描述 修改服务器端口 → server.port80 修改 banner → spring.main.banner off(关闭)/console(控制台)/log(日志) 日志 → logging.level.rootinfo Common Application Properties 配置文件分类 优先级 如果三种文件共存时&#xff0c;优先级为&am…...

vue中使用axios发送请求时,后端同一个session获取不到值

问题描述&#xff1a; 在登录页面加载完成后通过axios请求后端验证码接口&#xff08;这时后端会生成一个session用于保存验证码数值&#xff09;&#xff0c;当输入完用户名、密码、验证码后请求登录接口&#xff0c;报错验证码输入错误&#xff0c;打印后端保存验证码的sessi…...

html请求谷歌音频跨域问题(谷歌翻译接口)虚拟机ping不通google(下载谷歌音频、下载百度翻译音频)

文章目录 调用谷歌翻译接口&#xff0c;尝试了几种方案&#xff0c;都提示跨域不行第一种&#xff08;通过js代码获取音频文件的Blob对象&#xff0c;提示跨域了&#xff09;代码结果 第二种&#xff08;尝试新窗打开音频url&#xff0c;404&#xff0c;估计也是跨域了&#xf…...

【设计模式|结构型】享元模式(Flyweight Pattern)

概述 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构型设计模式&#xff0c;它旨在通过共享对象来减少系统中的对象数量&#xff0c;以便在有限的内存中节省空间和提高性能。在享元模式中&#xff0c;对象分为两部分&#xff1a;内部状态&#xff08;Intrinsic…...

最小覆盖子串(JS)

最小覆盖子串 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串&#xff0c;则返回空字符串 “” 。 注意&#xff1a; 对于 t 中重复字符&#xff0c;我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量…...

<C语言> 预处理和宏

1.预定义符号 __FILE__ //进行编译的源文件 __LINE__ //文件当前的行号 __DATE__ //文件被编译的日期 __TIME__ //文件被编译的时间 __STDC__ //如果编译器遵循ANSI C&#xff0c;其值为1&#xff0c;否则未定义这些预定义符号都是C语言内置的。 举个例子&…...

代驾公司如何进行运营分析

在这个快节奏的社会中&#xff0c;人们的生活节奏也在不断加快&#xff0c;对于代驾服务的需求也日益增长。然而&#xff0c;如何在这个竞争激烈的市场中&#xff0c;让订单稳稳地握在自己的手中&#xff0c;成为了每一个代驾公司都需要深思的问题。那么&#xff0c;代驾公司如…...

初学HTML:采用CSS绘制一幅夏天的图

下面代码使用了HTML和CSS来绘制一幅炎炎夏日吃西瓜的画面。其中&#xff0c;使用了伪元素和阴影等技巧来实现部分效果。 <!DOCTYPE html> <html> <head><title>炎炎夏日吃西瓜</title><style>body {background-color: #add8e6; /* 背景颜…...

经典文献阅读之--NoPe-NeRF(优化无位姿先验的神经辐射场)

0. 简介 在没有预先计算相机姿态的情况下训练神经辐射场&#xff08;NeRF&#xff09;是具有挑战性的。最近在这个方向上的进展表明&#xff0c;在前向场景中可以联合优化NeRF和相机姿态。然而&#xff0c;这些方法在剧烈相机运动时仍然面临困难。我们通过引入无畸变单目深度先…...

在docker中没有vi如何修改docker中的文件

今天在做学成在线的项目&#xff0c;遇到了一个问题&#xff0c;就是死活登不上xxl-job&#xff0c;按照之前遇到的nacos的问题&#xff0c;我怀疑很大概率是和当时的ip设置有关&#xff0c;不知道nacos的ip怎么修改的同学&#xff0c;可以看看这篇文章&#xff1a;关于docker中…...

【Docker】Docker应用部署之Docekr容器安装Nginx

目录 一、搜索镜像 二、拉取镜像 三、创建容器 四、测试使用 一、搜索镜像 docker search nginx 二、拉取镜像 docker pull nginx # 不加冒号版本号 默认拉取最新版 三、创建容器 首先我们需要在宿主机创建数据卷目录 mkdir nginx # 创建目录 cd nginx # 进入目录 mkd…...

flutter开发实战-jsontodart及 生成Dart Model类

flutter开发实战-jsontodart及 生成Dart Model类。 在开发中&#xff0c;经常遇到请求的数据Json需要转换成model类。这里记录一下Jsontodart生成Dart Model类的方案。 一、JSON生成Dart Model类 在开发中经常用到将json转成map或者list。通过json.decode() 可以方便 JSON 字…...

C++复刻:[流光按钮]+[悬浮波纹按钮]

目录 参考效果实现main.cppdialog.hdialog.cppflowingRayButton.h 流动光线按钮flowingRayButton.cpp 流动光线按钮hoveringRippleButton.h 悬浮波纹按钮hoveringRippleButton.cpp 悬浮波纹按钮模糊知识点 源码 参考 Python版本&#xff1a;GitHub地址 B站主页 效果 实现 ma…...

CompletableFuture 详解

目录 简单介绍 常见操作 创建 CompletableFuture new 关键字 静态工厂方法 处理异步结算的结果 简单介绍 CompletableFuture 同时实现了 Future 和 CompletionStage 接口。 public class CompletableFuture<T> implements Future<T>, CompletionStage<T…...

el-table数据处理

在写表格时遇到&#xff0c;后端返回的数据是对象&#xff0c;并且缺少字段 1.每一条数据加上 一个字段 2.将对象转成数组 以下是数据 {"groupA": {"groupName": null,"orgName": null,"orgId": null,"allPeoper": &quo…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...