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

2、Linux驱动开发:模块_引用符号

目录

🍅点击这里查看所有博文

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

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

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

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

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

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

什么是符号?

  这里的符号主要指的是全局变量和函数

  Linux内核采用的是以模块化形式管理内核代码。内核中的每个模块相互之间是相互独立的,也就是说A模块的全局变量和函数,B模块是无法访问的。

  不同模块间可通过导出宏,将符号导出,被导出的符号可被其他模块使用。

static int num = 100;
static void show(void)
{printk("aaaa:  num =%d \n",num);
}
EXPORT_SYMBOL(num);
EXPORT_SYMBOL(show);

Ubuntu中的符号表

  Linux内核的全局符号表在/usr/src/linux-headers-xxxxx-generic/Module.symvers。

root@ubuntu:# ls /usr/src/linux-headers-4.15.0-142-generic/
arch   crypto         firmware  init    Kconfig  Makefile        net      security  ubuntu
block  Documentation  fs        ipc     kernel   mm              samples  sound     usr
certs  drivers        include   Kbuild  lib      Module.symvers  scripts  tools     virt

  某个单独编译的内核符号表在代码根目录下。在模块编译好后,在它的当前目录会看到一个Module.symvers文件,这里存放的就是我们模块A导出的符号。

root@ubuntu:# ls
helloa.c   helloa.mod.c  helloa.o  modules.order
helloa.ko  helloa.mod.o  Makefile  Module.symvers

示例源码

  模块A的示例源码,在模块A中使用EXPORT_SYMBOL导出整型变量num和void型函数show。

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("PD");
static int num = 100;
static void show(void)
{printk("helloa_show num =%d \n",num);
}
static int hello_init(void)
{printk("helloa_init \n");return 0;
}
static void hello_exit(void)
{printk("helloa_exit \n");return;
}
EXPORT_SYMBOL(num);
EXPORT_SYMBOL(show);
module_init(hello_init);
module_exit(hello_exit);

  在模块B中直接使用extern引入外部的定义即可。

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("PD");
extern int num;
extern  void show(void);
static int hello_init(void)
{printk("hellob_init %d\n",num);show();return 0;
}
static void hello_exit(void)
{printk("hellob_exit \n");return;
}
module_init(hello_init);
module_exit(hello_exit);

引用步骤

  编译模块A,将模块A编译生成的Module.symvers文件拷贝到模块 B目录下(可选),不拷贝的话,在编译B时也只是会报一个警告,不影响使用。建议拷贝,程序员不能忽视任何一个警告才是对的。

WARNING: "show" [/home/peng/Desktop/driver/example/2_export/b/hellob.ko] undefined!
WARNING: "num" [/home/peng/Desktop/driver/example/2_export/b/hellob.ko] undefined!

  编译模块B,操作正确的情况下,正常是不会有任何的错误和警告的。

root@ubuntu:# make
make -C /lib/modules/4.15.0-142-generic/build M=/home/peng/Desktop/driver/example/2_export/b modules
make[1]: Entering directory '/usr/src/linux-headers-4.15.0-142-generic'CC [M]  /home/peng/Desktop/driver/example/2_export/b/hellob.oBuilding modules, stage 2.MODPOST 1 modules
WARNING: "show" [/home/peng/Desktop/driver/example/2_export/b/hellob.ko] undefined!
WARNING: "num" [/home/peng/Desktop/driver/example/2_export/b/hellob.ko] undefined!CC      /home/peng/Desktop/driver/example/2_export/b/hellob.mod.oLD [M]  /home/peng/Desktop/driver/example/2_export/b/hellob.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.15.0-142-generic'

  先加载模块A,然后加载模块B。从日志中分析可知在加载模块A时,先执行了helloa的加载函数。加载模块B的过程中执行模块B加载函数时,首先引用了模块a的变量num,紧接着又调用了模块A中show函数。

root@ubuntu:# insmod ./helloa.ko
root@ubuntu:# insmod ./hellob.ko
root@ubuntu:# dmesg
[ 8167.354563] helloa_init 
[ 8170.907883] hellob_init 100
[ 8170.907884] helloa_show num =100

注意事项

  加载的时候,必须先加载A模块,再加载B模块。否则会报错Unknown symbol in module

root@ubuntu:# insmod ./hellob.ko
insmod: ERROR: could not insert module ./hellob.ko: Unknown symbol in module
root@ubuntu:# insmod ./helloa.ko
root@ubuntu:# insmod ./hellob.ko

  卸载的时候,必须先卸载B模块,再卸载A模块。否则会报错Module helloa is in use by

root@ubuntu:# rmmod ./helloa.ko
rmmod: ERROR: Module helloa is in use by: hellob
root@ubuntu:# rmmod ./hellob.ko
root@ubuntu:# rmmod ./helloa.ko

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

相关文章:

2、Linux驱动开发:模块_引用符号

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

Python web实战 | Docker+Nginx部署python Django Web项目详细步骤【干货】

概要 在这篇文章中&#xff0c;我将介绍如何使用 Docker 和 Nginx 部署 Django Web 项目。一步步讲解如何构建 Docker 镜像、如何编写 Docker Compose 文件和如何配置 Nginx。 1. Docker 构建 Django Web 项目 1.1 配置 Django 项目 在开始之前&#xff0c;我们需要有一个 D…...

【uniapp】实现买定离手小游戏

前言 最近玩了一个小游戏&#xff0c;感觉挺有意思&#xff0c;打算放进我的小程序【自动化小助手】里面&#xff0c;“三张押一张&#xff0c;专押花姑娘&#xff01;”&#xff0c;从三张卡牌&#xff0c;挑选一张&#xff0c;中奖后将奖励进行发放&#xff0c;并且创建下一…...

【vim 学习系列文章 3 - vim 选中、删除、复制、修改引号或括号内的内容】

文章目录 vim 快捷命令vim 操作符vim 文本对象vim 动作 上篇文章: vim 学习系列文章 2 - vim 常用插件配置 vim 快捷命令 Vim 有一个模块化的结构&#xff0c;允许你使用各种命令的组合操作。大多数命令有两个、三个或四个部分。三部分结构的一个版本是这样的&#xff1a;操作…...

webpack联邦模块介绍及在dumi中使用问题整理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、ModuleFederationPlugin参数含义&#xff1f;二、如何在dumi中使用及问题整理1. 如何在dumi中使用(这个配置是好使的)2.相关问题整理2.1 问题12.2 问题2 总…...

记录一下Kotlin: Module was compiled with an incompatible version of Kotlin.的问题

我遇到的整个报错是这样的&#xff1a; Error:Kotlin: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.7.1, expected version is 1.1.16. 大概意思就是不匹配&#xff0c;但是我这是个不太能随便改代码的项目&#x…...

html中使用Vue+element UI动态创建表单数据不显示问题

直接上代码&#xff1a;html代码如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content&…...

CentOS下 Docker、Docker Compose 的安装教程

Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间不会有任何接口。 Docker Compose是用于定义…...

[OnWork.Tools]系列 02-安装

下载地址 百度网盘 历史版本连接各种版本都有,请下载版本号最高的版本 链接&#xff1a;https://pan.baidu.com/s/1aOT0oUhiRO_L8sBCGomXdQ?pwdn159提取码&#xff1a;n159 个人链接 http://on8.top:5000/share.cgi?ssiddb2012fa6b224cd1b7f87ff5f5214910 软件安装 双…...

【外键合并python】

外键合并&#xff08;Foreign Key Merge&#xff09; 外键合并是指在数据库或者数据表中&#xff0c;通过共同的外键将多个数据表合并在一起的操作。在 Excel 表格中&#xff0c;我们可以使用外键来将多个表格合并&#xff0c;类似于数据库中的关联操作。 步骤一&#xff1a;…...

Mongodb SQL 到聚合映射快速参考

SQL 映射 聚合管道允许MongoDB 提供原生聚合功能&#xff0c;对应于 SQL 中许多常见的数据聚合操作。比如&#xff1a;GROUP BY、COUNT()、UNION ALL 测试数据 For MySQL rootlocalhost 14:40:40 [test]> select * from orders; -------------------------------------…...

腾讯云标准型S6/SA3/SR1/S5/SA2服务器CPU处理器大全

腾讯云服务器CVM标准型CPU处理器大全&#xff0c;包括标准型S6、SA3、SR1、S5、S5se、SA2、S4、SN3ne、S3、SA1、S2ne实例CPU处理器型号大全&#xff0c;标准型S6云服务器CPU采用Intel Ice Lake(2.7GHz/3.3GHz)&#xff0c;标准型S5采用Intel Xeon Cascade Lake 8255C/Intel Xe…...

idea 关于高亮显示与选中字符串相同的内容

dea 关于高亮显示与选中字符串相同的内容&#xff0c;本文作为个人备忘的同时也希望可以作为大家的参考。 依次修改File-settings-Editor-Color Scheme-General菜单下的Code-Identifier under caret和Identifier under caret(write)的Backgroud色值&#xff0c;可以参考下图。…...

【重点:单例模式】特殊类设计

请设计一个类&#xff0c;只能在堆上创建对象 方式如下&#xff1a; 将构造函数设置为私有&#xff0c;防止外部直接调用构造函数在栈上创建对象。向外部提供一个获取对象的static接口&#xff0c;该接口在堆上创建一个对象并返回。将拷贝构造函数设置为私有&#xff0c;并且…...

智能家居是否可与ChatGPT深度融合?

​ ChatGPT自2022年面世以来&#xff0c;已为亿万网民提供智能问答服务。然而我们是否曾想到&#xff0c;这一人工智能驱动的聊天机器人&#xff0c;是否可为智能家居赋能? 要实现ChatGPT与智能家居设备之间的无缝对话&#xff0c;单单依靠一台终端是远远不够的。ChatGPT必须…...

LED芯片 VAS1260IB05E 带内部开关LED驱动器 汽车硬灯带灯条解决方案

VAS1260IB05E深力科LED芯片是一种连续模式电感降压转换器&#xff0c;设计用于从高于LED电压的电压源高效驱动单个或多个串联连接的LED。该设备在5V至60V之间的输入电源下工作&#xff0c;并提供高达1.2A的外部可调输出电流。包括输出开关和高侧输出电流感测电路&#xff0c;该…...

微信小程序插件 painter 生成海报、二维码

GitHub 地址&#xff1a;https://github.com/Kujiale-Mobile/Painter 一、引入 将 components/painter 整个文件放到自己项目的 components 中&#xff1b;以组件的形式在页面的 json 文件中引入&#xff1b; 二、使用 <view class"container"><image s…...

Python版day60

84. 柱状图中最大的矩形 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 class Solution:def largestRectangleArea(self, heights: List[int]) -> i…...

windows C++多线程同步<3>-互斥量

windows C多线程同步&#xff1c;3&#xff1e;-互斥量 概念&#xff0c;如下图&#xff1a; 另外就是互斥对象谁拥有&#xff0c;谁释放 那么一个线程允许多次获取互斥对象吗&#xff1f; 答案是允许&#xff0c;但是申请多次就要释放多次&#xff0c;否则其他线程获取不到互…...

(学习笔记-系统结构)Linux内核与windows内核

内核 计算机是由各种外部硬件设备组成的&#xff0c;比如内存、CPU、硬盘等&#xff0c;如果每个应用都要和这些硬件设备对接通信协议&#xff0c;那这样太累了&#xff0c;所以这个中间人由内核来负责&#xff0c;让内核作为应用连接硬件设备的桥梁&#xff0c;应用程序只关心…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

Python 训练营打卡 Day 47

注意力热力图可视化 在day 46代码的基础上&#xff0c;对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

Axure 下拉框联动

实现选省、选完省之后选对应省份下的市区...

向量几何的二元性:叉乘模长与内积投影的深层联系

在数学与物理的空间世界中&#xff0c;向量运算构成了理解几何结构的基石。叉乘&#xff08;外积&#xff09;与点积&#xff08;内积&#xff09;作为向量代数的两大支柱&#xff0c;表面上呈现出截然不同的几何意义与代数形式&#xff0c;却在深层次上揭示了向量间相互作用的…...