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

模块?当做进程理解,你将豁然开朗

目录一、为什么驱动开发中不能类似函数直接传参二、module_param的原理与使用1代码示例与运行结果2static与module_param的作用与原理3最后一个参数与伪文件的关系三、符号共享(1)如何理解模块类比进程即可2为什么需要符号共享3符号共享调用的接口本篇文章类比了进程来理解驱动本质都是Linux内核中的一个结构体罢了。然后进程有的驱动模块也一定会有类似的功能。比如进程间通信、进程的命令行参数直接对应到模块的符号共享、module_param。一、为什么驱动开发中不能类似函数直接传参无论是应用层开发还是裸机开发似乎都可以直接给函数写形参调用的时候直接传递参数啊为什么到了内核中的驱动开发就行不通了首先函数调用传参是 CPU 指令集与 ABI应用二进制接口定义的能力依赖寄存器 / 栈来完成这一点本身没错但它只适用于编译期确定调用关系的场景。在裸机开发中代码被编译后就形成了 “硬编码”需要的参数都直接被编译器写好放在栈帧中等待函数去调用拿取该变量 —— 因为裸机环境没有动态加载所有函数调用关系在编译时就完全固定。其次在有操作系统时上层应用临时创建一个进程给该进程传参是通过 ** 命令行参数argv和环境变量envp** 实现的由 Linux 内核在execve系统调用时完成参数拷贝与传递这是进程级的传参机制和函数级传参是两回事。但是在驱动开发中驱动本身属于内核的一部分模块加载是动态且异步的驱动何时加载、由谁加载都不确定无法像裸机那样在编译期把参数硬编码到内存也没有更底层的组件来为module_init封装 “函数级传参” 的调用逻辑。如果强行为每个模块预写参数到内存会造成极大的内存浪费与管理开销。因此驱动开发中传参的思考方向和环境变量、命令行参数高度类似 —— 都是在加载时动态传递而非编译期绑定。最后由于每一种驱动可能需要的形参类型、个数是不同的如果为module_init设计可变形参会极大增加内核模块加载器的复杂度与兼容性风险。所以设计模块加载函数module_init的人直接就写死了形参必须是void通过 ** 内核专门的模块参数机制module_param** 来替代函数形参实现更灵活、通用的参数传递。这个行为有点像创建线程时固定形参为void*的做法同时又类似 shell 命令行参数与环境变量的设计我认为本质是一致的为了保证接口通用性先固定入口函数的形参格式再通过外部扩展机制实现灵活传参。只不过命令行参数是内核在创建新进程时向用户态进程传递初始数据忽略了从shell到内核的过程而驱动传参是内核在加载模块时向内核态模块注入初始参数。二者是一个相反的逻辑过程都遵循 “加载时动态传参” 的设计逻辑内核模块参数的设计思路很大概率正是从 shell 命令行参数与环境变量的实现中得到了启发。二、module_param的原理与使用通过前面的介绍你大概就能明白了module_param就是适配驱动的“命令行参数”。它的存在使得想要驱动工作在不同配置模式下时不需要修改代码重新编译而是直接在insmod的时候添加一些键值对参数即可。典型场景调试阶段快速修改日志级别、设备地址、超时时间避免反复编译。生产环境同一个.ko文件适配不同硬件 / 业务场景通过加载时传参区分配置。动态调优运行时修改参数如缓冲区大小、工作线程数无需重启服务。1代码示例与运行结果#includelinux/kernel.h #includelinux/module.h #includelinux/init.h //定义几个变量方便测试驱动命令行参数 //static的作用是让该变量只能在该文件被看到一般来说一个文件下只会写一个驱动模块 //所以经过module_param加载最后的效果就是只有该驱动模块能识别到该变量了 static int temp_int0; static char temp_char0; static char* temp_charphmy-default-string; //使用module_param将这几个变量加载到该模块中 module_param(temp_int,int,0664); module_param(temp_char,byte,0664); module_param(temp_charp,charp,0664); static int __init param_init(void) { printk(param模块开始测试\n); printk(temp_int:%d\n,temp_int); printk(temp_char:%c\n,temp_char); printk(temp_charp:%s\n,temp_charp); return 0; } static void __exit param_exit(void) { printk(param模块测试结束\n); } module_init(param_init); module_exit(param_exit); MODULE_LICENSE(GPL);2static与module_param的作用与原理static的作用是将该变量限制在当前文件可视范围内使得其他文件无法感知到该变量的存在而通常一个文件中只会写一个驱动模块这是Linux内核编译模块的强行规定一个文件写两个驱动模块会编译不通过所以这样做的结果就是只让该驱动模块能看到特定变量。保证该变量的模块私有性。module_param是内核提供的预处理宏它的作用是将变量与参数名绑定、设置访问权限并向内核注册参数元信息。module_param的本质是在编译期由宏展开构建一structkernel_param结构体填写变量名、类型操作集、权限值、变量地址等信息然后将该结构体放入当前模块私有的_param段中。最后在insmod加载模块时内核从该模块的_param段中提取结构体信息如果加载时动态传入了参数值内核会根据结构体中记录的变量地址直接将新值写入该地址对应的模块变量中相当于每个模块在共享内核地址空间中有自己的私有内存区域而_param段是模块的参数元数据供insmod加载时解析并完成变量赋值。相当于每个模块有自己的地址空间而__param段是一个前导引言需要被insmod加载到具体实例变量中。3最后一个参数与伪文件的关系注意到最后一个参数是用来形容该变量的权限的。常见的权限如下给可执行权限会被忽略不计Linux内核会为每一个经过module_param注册且权限值不为0的变量创建一个文件。他是基于内核的虚拟文件系统生成的“伪文件”。该伪文件的路径是/sys/module/驱动模块名称/parameters/变量名这个文件的操作和普通暴露给上次的文件系统一致可以读写echo、cat等操作。这意味着你可以在运行的时候通过指令修改该文件的内容即运行时修改变量的值。三、符号共享(1)如何理解模块类比进程即可在学习符号共享之前我们先来看看模块在Linux内核中是如何定义的惊讶的发现它和进程的组织、管理遵循同一套逻辑“先描述、后管理”。而内核模块的层级与之前学过的用户态进程的层级也极其类似:2为什么需要符号共享在应用开发的时候不可避免的需要用到进程间通信他是通过IPC提供的机制实现的可以通过共享内存、消息队列等方式让数据、指令从进程A传递到进程B。那么既然内核模块能类比成进程他们是否也有类似进程间通信的操作呢在进程通信的时候他本质是走的进程A的用户态地址空间-内核地址空间-进程B的用户态地址空间其中数据至少进行了2轮拷贝。再加上权限、地址空间的切换开销还是很大的所以进程间通信性能较低。而内核模块间的通信由于同处于内核地址空间没有任何多余的拷贝、权限切换开销性能大幅提升。3符号共享调用的接口模块1 #includelinux/kernel.h #includelinux/module.h #includelinux/init.h //定义几个变量方便测试驱动命令行参数 //static的作用是让该变量只能在该文件被看到一般来说一个文件下只会写一个驱动模块 //所以经过module_param加载最后的效果就是只有该驱动模块能识别到该变量了 static int temp_int0; static char temp_char0; static char* temp_charphmy-default-string; //使用module_param将这几个变量加载到该模块中 module_param(temp_int,int,0664); module_param(temp_char,byte,0664); module_param(temp_charp,charp,0664); int my_addfunc_int(int a,int b) { return ab; } //导出该函数到总符号表使得其他模块可以自由调用该函数类似进程间通信 EXPORT_SYMBOL(my_addfunc_int); static int __init param_init(void) { printk(param模块开始测试\n); printk(temp_int:%d\n,temp_int); printk(temp_char:%c\n,temp_char); printk(temp_charp:%s\n,temp_charp); printk(----------------------\n); return 0; } static void __exit param_exit(void) { printk(temp_int:%d\n,temp_int); printk(temp_char:%c\n,temp_char); printk(temp_charp:%s\n,temp_charp); printk(param模块测试结束\n); } module_init(param_init); module_exit(param_exit); MODULE_LICENSE(GPL);模块2 #includelinux/kernel.h #includelinux/module.h #includelinux/init.h extern int my_addfunc_int(int a,int b); //模块2 static int __init test_init(void) { int answermy_addfunc_int(1,5); printk(我使用了全局符号表中的符号15结果为%d\n,answer); printk(符号共享模块测试开始\n); return 0; } static void __exit test_exit(void) { printk(符号共享模块测试结束\n); } module_init(test_init); module_exit(test_exit); MODULE_LICENSE(GPL);当我们写好两个模块并且其中一方使用“导出”功能后为什么对方还是使用不了呢其实是因为编译器是把两个模块分开编译的在编译test2时发现你直接调用了my_addfunc_int函数但是你却在本文件中未曾定义所以需要用extern进行声明告诉编译器“这个函数在其他文件中已经定义了不要在编译阶段卡我错误”。可以看到最终模块2正确的调用了模块1的函数不过值得注意的是1由于两个模块都采用同样的编译器所以如果两个模块有同名变量、函数。则生成的符号是完全相同的此时如果导出可能会出错直接编译失败。2因为导出函数的实现在模块1中如果你的模块1还未加载就去加载模块2并且调用会报错因为此时真的找不到该符号。必须要保证你所引用的函数所处的模块已经加载好了。关于模块自动加载、卸载保持顺序要求也是能做到的这一点大家可以用到的时候再查查资料。

相关文章:

模块?当做进程理解,你将豁然开朗

目录 一、为什么驱动开发中不能类似函数直接传参? 二、module_param的原理与使用 (1)代码示例与运行结果 (2)static与module_param的作用与原理 (3)最后一个参数与(伪&#xff…...

Qwen3.5-35B-A3B-AWQ-4bit多场景落地:农业病虫害图识别、法律文书图证分析

Qwen3.5-35B-A3B-AWQ-4bit多场景落地:农业病虫害图识别、法律文书图证分析 1. 引言:当AI学会“看图说话” 想象一下,你是一位农业技术员,在田间地头发现一片叶子有异常斑点,你掏出手机拍张照,上传到一个系…...

AI技术辅助下的软件工程学术论文创作与代码重现方法

文章总结表格(工具排名对比) 工具名称 核心优势 aibiye 精准降AIGC率检测,适配知网/维普等平台 aicheck 专注文本AI痕迹识别,优化人类表达风格 askpaper 快速降AI痕迹,保留学术规范 秒篇 高效处理混AIGC内容&…...

Windows系统优化咨询:Qwen3-0.6B-FP8解答C盘清理与更新管理问题

Windows系统优化咨询:Qwen3-0.6B-FP8解答C盘清理与更新管理问题 最近在折腾一个很有意思的AI小助手,它叫Qwen3-0.6B-FP8。别看它模型不大,但处理起日常问题来,思路特别清晰,像个经验丰富的电脑管家。正好手头有台Wind…...

如何开发一款企业级人才招聘系统?招聘APP源码与技术实现

博主介绍: 所有项目都配有从入门到精通的安装教程,可二开,提供核心代码讲解,项目指导。 项目配有对应开发文档、解析等 项目都录了发布和功能操作演示视频; 项目的界面和功能都可以定制,包安装运行&#xf…...

ONLYOFFICE 宏实战:从 VBA 迁移到 JavaScript 的自动化技巧

1. 为什么需要从 VBA 迁移到 JavaScript 宏? 如果你曾经在 Excel 里用过 VBA 宏,肯定体验过它带来的效率提升。但当你开始使用 ONLYOFFICE 时,会发现这个办公套件采用了完全不同的 JavaScript 宏系统。这就像开惯了手动挡汽车突然要换自动挡…...

swoole方案 统一鉴权与鉴权代理中心

<?php /*** 鉴权代理网关** 大白话流程&#xff1a;* 请求进来 → 验JWT → 通过了 → 转发给PHP-FPM后端* → 不通过 → 直接拒绝&#xff0c;后端根本看不到这个请求** 为什么这么做&#xff1a;* PHP-FPM 每个请求都要启动框架、连数据库验toke…...

别再让PID调参折磨你了:手把手教你用积分分离和变速积分搞定电机定位不准

电机精准定位的PID调参实战&#xff1a;积分分离与变速积分的黄金组合 机械臂末端总是抖动停不准&#xff1f;云台回中时反复震荡&#xff1f;这些让工程师头疼的定位问题&#xff0c;90%源于PID积分项的粗放管理。传统调参方法像用钝刀雕花——要么积分不足导致静差残留&#…...

关于岩溶隧道突水渗流及围岩损伤的流固耦合行为分析的全面探讨(500M参考资源的岩土建模技术与方法)

Comsol隧道围岩流固耦合 1主题&#xff1a;岩溶隧道突水渗流和损伤 2内容&#xff1a;mph文件、力学参数文件&#xff0c;围岩损伤课题参考文献&#xff08;500M&#xff09; 3备注&#xff1a;看懂每一步建模过程&#xff0c;特别注意研究模态及matlab和comsol的连接&#xff…...

无需代码基础!LiuJuan20260223Zimage开箱即用:WebUI一键生成创意图片

无需代码基础&#xff01;LiuJuan20260223Zimage开箱即用&#xff1a;WebUI一键生成创意图片 1. 引言&#xff1a;让创意图片生成变得简单 你是否曾经遇到过这样的情况&#xff1a;想要一张独特的创意图片&#xff0c;但既不会使用专业设计软件&#xff0c;也没有绘画基础&am…...

基于大语言模型的交易策略感知型电价预测方法研究

由于这是一个完整的学术研究方案,将构建一份详尽的文档,包含方法论、代码实现、模型架构、损失函数设计及实验分析。将提供深入的理论推导、完整的Python代码(基于PyTorch及HuggingFace Transformers)以及详细的代码解释。 基于大语言模型的交易策略感知型电价预测方法研究…...

PADS Logic格点设置优化指南:提升设计效率与美观性

1. 为什么格点设置如此重要&#xff1f; 刚接触PADS Logic时&#xff0c;我和很多新手一样&#xff0c;觉得格点设置就是个可有可无的小功能。直到有一次设计一个复杂电路板&#xff0c;元件摆放怎么都对不齐&#xff0c;连线歪歪扭扭像蚯蚓爬&#xff0c;才意识到格点的重要性…...

Git贡献全流程:从入门到进阶

开源项目Git贡献全流程拆解准备工作注册GitHub/GitLab等代码托管平台账号安装Git并配置基础信息&#xff08;用户名、邮箱&#xff09;熟悉基础Git命令&#xff08;clone、commit、push等&#xff09;了解目标项目的贡献规范&#xff08;CONTRIBUTING.md&#xff09;寻找合适的…...

SAS程序员必看:ADaM数据集里这8个函数,能帮你省下一半调试时间

SAS程序员效率革命&#xff1a;ADaM数据集8个核心函数的深度实战指南 临床试验统计分析编程中&#xff0c;ADaM数据集的构建往往占据SAS程序员70%以上的工作时间。当项目周期压缩到两周时&#xff0c;如何用函数组合替代冗长的条件判断和循环逻辑&#xff0c;成为区分普通程序员…...

效率对比实测:OpenClaw+GLM-4.7-Flash与传统RPA工具任务完成速度

效率对比实测&#xff1a;OpenClawGLM-4.7-Flash与传统RPA工具任务完成速度 1. 测试背景与实验设计 去年我在团队内部推动自动化工具选型时&#xff0c;发现传统RPA工具虽然稳定&#xff0c;但面对非结构化数据处理时显得力不从心。最近接触到OpenClaw框架后&#xff0c;决定…...

PP-DocLayoutV3行业落地:法律合同要素定位、医疗报告结构识别实战解析

PP-DocLayoutV3行业落地&#xff1a;法律合同要素定位、医疗报告结构识别实战解析 1. 新一代文档布局分析引擎&#xff1a;突破传统限制 在日常工作中&#xff0c;我们经常需要处理各种文档——扫描的合同、拍摄的报告、电子文档截图等。传统文档分析工具往往只能识别规整的矩…...

比迪丽SDXL效果展示:多语言提示词支持(中/英/日)实测报告

比迪丽SDXL效果展示&#xff1a;多语言提示词支持&#xff08;中/英/日&#xff09;实测报告 1. 引言&#xff1a;当《龙珠》角色遇上AI绘画 如果你是《龙珠》的粉丝&#xff0c;一定对那个坚强、勇敢的比迪丽印象深刻。现在&#xff0c;有个好消息&#xff1a;通过AI绘画技术…...

COMSOL仿真模型下的石墨烯与钙钛矿太阳能电池光电耦合模型研究

COMSOL石墨烯/钙钛矿太阳能电池仿真模型。 光电耦合模型&#xff0c;文章复现。在太阳能电池的研究领域&#xff0c;石墨烯和钙钛矿的结合无疑是一个热门话题。今天&#xff0c;我们来聊聊如何在COMSOL中构建一个石墨烯/钙钛矿太阳能电池的仿真模型&#xff0c;特别是光电耦合模…...

告别手动录入!用WfForm API实现泛微E9明细表数据自动填充(附完整JS代码)

泛微E9智能表单实战&#xff1a;基于WfForm API的明细表动态填充技术解析 在OA系统实施过程中&#xff0c;明细表数据的手动录入一直是效率瓶颈。以采购申请为例&#xff0c;当选择"紧急采购"状态时&#xff0c;需要自动加载备用供应商清单&#xff1b;在设备报修场景…...

老旧Intel Mac系统焕新指南:用OpenCore Legacy Patcher实现设备重生

老旧Intel Mac系统焕新指南&#xff1a;用OpenCore Legacy Patcher实现设备重生 【免费下载链接】OpenCore-Legacy-Patcher 体验与之前一样的macOS 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher OpenCore Legacy Patcher是一款强大的开源…...

AI 写代码快得飞起,但怎么让生成的项目能改、能维护、不崩?

AI Coding 让代码生成速度飙升&#xff0c;但“跑通”绝不等于“可维护”。当团队沉浸在快速上线的快感中时&#xff0c;往往忽略了底层隐患。不少开发者发现&#xff0c;缺乏像 Oinone 这样具备严格框架纪律的工程化底座&#xff0c;生成的系统就像临时拼装的乐高&#xff0c;…...

VITS凭什么能“以假乱真”?拆解其背后让语音更自然的三个设计巧思

VITS如何突破语音合成的自然度瓶颈&#xff1f;三大核心技术解析 在语音合成领域&#xff0c;从早期的拼接式系统到如今的神经网络模型&#xff0c;技术迭代始终围绕一个核心目标&#xff1a;如何让机器发出的声音更像真人。传统TTS系统虽然已经能够生成清晰可懂的语音&#xf…...

CosyVoice数据库应用实战:结合MySQL存储与管理海量语音资产

CosyVoice数据库应用实战&#xff1a;结合MySQL存储与管理海量语音资产 想象一下&#xff0c;你正在开发一个智能客服系统&#xff0c;每天需要为成千上万的用户生成个性化的语音回复。或者&#xff0c;你在做一个有声书平台&#xff0c;需要管理数万本图书的语音合成资产。很…...

Wan2.1 VAE爬虫数据增强实战:将爬取的图像数据转化为统一艺术风格

Wan2.1 VAE爬虫数据增强实战&#xff1a;将爬取的图像数据转化为统一艺术风格 你有没有遇到过这种情况&#xff1f;辛辛苦苦从网上爬下来一堆图片&#xff0c;准备用来训练自己的AI模型&#xff0c;结果发现这些图片风格五花八门——有的明亮&#xff0c;有的灰暗&#xff0c;…...

Deepsort跟踪器在车辆检测中的表现如何?我用MOT16数据集做了这些实验

DeepSORT在车辆跟踪中的实战评估&#xff1a;从MOT16数据集改造到指标分析 当目标跟踪技术从学术研究走向工业落地时&#xff0c;车辆跟踪成为智能交通和自动驾驶领域的关键环节。本文将带您深入探索如何将原本针对行人跟踪设计的MOT16数据集改造为车辆跟踪评估基准&#xff0c…...

Jupyter Notebook新手必看:5分钟搞定环境配置与常见问题解决

Jupyter Notebook新手极简指南&#xff1a;从零配置到高效编码 第一次打开Jupyter Notebook时&#xff0c;那种既期待又忐忑的心情我至今记忆犹新——面对这个看似简单却功能强大的交互式笔记本工具&#xff0c;如何快速搭建起自己的开发环境&#xff1f;本文将带你用最短的时…...

从零开始C语言调用MiniCPM-V-2_6:轻量级本地推理引擎开发

从零开始C语言调用MiniCPM-V-2_6&#xff1a;轻量级本地推理引擎开发 1. 引言 如果你是一名嵌入式开发者&#xff0c;或者正在为一个资源受限的边缘设备寻找AI能力&#xff0c;那么“用C语言直接调用大模型”这个想法&#xff0c;可能既让你兴奋&#xff0c;又让你觉得无从下…...

别再死记硬背了!用Python代码和动画图解帮你彻底搞懂DFA/NFA(附Jupyter Notebook)

用Python代码与动画彻底掌握DFA/NFA&#xff1a;从理论到正则表达式引擎实战 引言&#xff1a;为什么我们需要可视化学习自动机理论&#xff1f; 第一次接触有限自动机概念时&#xff0c;你是否曾被那些抽象的状态转移图弄得晕头转向&#xff1f;作为计算机科学的核心基础理论&…...

python学习笔记--集和的内置方法

# 集合的特点是无序且去重 # 集合 变量名 {元素1,元素2, 元素3, ...} # 【1】支持类型强制转换 # 可以将其他类型转换为 集合 print(set("dreammmmm")) # {m, d, e, a, r} print(set(list("dreammmmm"))) # {m, d, e, a, r} print(set(tuple("dream…...

深刻思考Python 装饰器——不输Java Aop的切面编程利器

先说结论 java 注解能实现的功能&#xff0c;python 的装饰器绝大部分都是可以胜任的&#xff0c;装饰器更像 Java 中注解加上Aop两者的组合 python 是一门极简的语言&#xff0c;语言简洁学习起来也是相当轻松的&#xff0c;但是依然有一些高级技巧&#xff0c;例如装饰器&am…...