【Linux驱动开发100问】什么是模块?如何编写和使用模块?
🥇今日学习目标:什么是Linux内核?
🤵♂️ 创作者:JamesBin
⏰预计时间:10分钟
🎉个人主页:嵌入式悦翔园个人主页
🍁专栏介绍:Linux驱动开发100问
什么是模块?如何编写和使用模块?
- 一、什么是模块
- 二、如何编写模块
- 三、如何编译模块
- 四、如何挂载和卸载模块
- 五、如何使用模块
- 六、相关知识
一、什么是模块
在 Linux 内核中,模块是一种动态加载和卸载的可执行文件,它可以在运行时向内核添加新的功能和驱动。 与编译进内核的代码相比,模块的使用可以减少内核的体积和启动时间,并且可以让内核更加灵活,根据需要动态地添加或删除功能。
模块可以是设备驱动、文件系统、网络协议、安全模块等,通过内核提供的模块管理接口,可以动态地插入和删除模块。模块的代码通常是以源码形式提供,需要编译成二进制文件才能加载到内核中运行。模块也可以被其他模块所依赖,形成模块之间的依赖关系。
模块的使用可以帮助我们解决很多问题,例如:
- 节省内存空间:模块可以按需加载,不需要一直占用内存,从而节省内存空间。
- 扩展内核功能:模块可以添加新的设备驱动程序、文件系统、网络协议等内核功能。
- 提高系统安全性:模块可以对内核进行功能增强,从而提高系统的安全性。
总之,模块是Linux内核中一个非常重要的组成部分,可以让内核变得更加灵活、可扩展和可维护。
Linux模块可以是驱动,也可以是其他功能模块。模块和驱动之间存在一定的关系,因为驱动通常也是作为模块的形式存在于内核中的。
在Linux内核中,模块可以被动态地插入和卸载,因此模块通常被用来扩展内核的功能。而驱动则是一种特殊的模块,用于管理硬件设备,控制硬件设备的操作。在Linux中,驱动通常也以模块的形式存在于内核中,从而使得内核可以支持更多的硬件设备。因此,可以说驱动是模块的一种特殊形式。
二、如何编写模块
编写Linux内核模块需要遵循以下步骤:
1、包含必要的头文件
在C文件的开头,需要包含一些头文件,比如<linux/module.h>
和<linux/init.h>
等,这些头文件包含了模块开发所需的函数和宏等。
2、编写模块初始化和退出函数
模块初始化函数是模块载入时调用的函数,模块退出函数是模块被卸载时调用的函数。模块初始化函数需要使用宏module_init
进行定义,模块退出函数需要使用宏module_exit
进行定义。
3、定义模块许可证
Linux内核模块的代码需要遵循一定的许可证,这可以在模块代码中使用宏MODULE_LICENSE
进行定义。
4、编写模块代码
这是编写模块最主要的部分。模块代码需要定义模块的功能,并提供接口以便其他程序可以使用这些功能。
下面是一个简单的Linux内核模块代码示例:
#include <linux/module.h> // 模块头文件
#include <linux/init.h> // 初始化函数头文件static int __init hello_init(void) // 初始化函数
{printk(KERN_ALERT "Hello, world!\n"); // 打印信息return 0;
}static void __exit hello_exit(void) // 退出函数
{printk(KERN_ALERT "Goodbye, cruel world!\n"); // 打印信息
}MODULE_LICENSE("Dual BSD/GPL"); // 定义许可证module_init(hello_init); // 定义初始化函数
module_exit(hello_exit); // 定义退出函数
三、如何编译模块
编译 Linux 模块可以使用 make
工具来完成,需要使用内核源码目录中的 Makefile 文件。下面是具体步骤:
进入 Linux 内核源码目录,并切换到要编译的内核版本分支。
运行命令 make modules_prepare
,该命令会生成 Module.symvers
文件,该文件包含了内核中所有可导出符号的信息,包括符号名、地址和版本等。
进入模块源码所在的目录,并创建一个名为 Makefile 的文件。
在 Makefile 文件中添加以下内容:
obj-m := module_name.o
其中 module_name
表示模块的名称,.o
表示编译后生成的目标文件格式。
运行命令
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
-C
选项指定内核源码目录,$(uname -r)
表示当前系统运行的内核版本号。
M
选项指定模块源码目录。
如果编译成功,将会生成一个名为 module_name.ko
的文件,该文件即为编译后的模块文件。
四、如何挂载和卸载模块
我们上一步骤通过make命令编译出来的.ko文件即为在最终的模块文件,如果想要使用该模块文件还需要使用 insmod
命令加载模块,例如:
$ sudo insmod module_name.ko
如果需要卸载模块,可以使用 rmmod
命令,例如:
$ sudo rmmod module_name
注意,在加载和卸载模块时需要拥有管理员权限。
为什么要挂载和卸载模块?
在Linux内核中,模块是可以被动态加载和卸载的。当内核启动时,并不会将所有的模块都加载进来,而是按需加载,这样可以提高系统的启动速度和节省内存空间。
当需要使用某个模块时,就需要将它挂载到内核中,使得内核能够调用模块中的功能。而当不再需要某个模块时,可以将其从内核中卸载,释放内存空间。因此,模块的挂载和卸载是为了方便动态管理模块的加载和卸载,提高系统的效率和稳定性。
五、如何使用模块
假设我们已经编写好了一个名为hello_module的内核模块,现在需要编写一个测试程序来调用该模块。下面是一个简单的测试程序代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>int main()
{int fd = open("/dev/hello", O_RDWR);if (fd < 0) {perror("Failed to open device /dev/hello");exit(1);}char buf[32];int ret = read(fd, buf, sizeof(buf));if (ret < 0) {perror("Failed to read from device /dev/hello");close(fd);exit(1);}printf("Read from /dev/hello: %s\n", buf);close(fd);return 0;
}
该测试程序的作用是打开内核模块创建的设备文件/dev/hello
,然后从设备文件中读取数据并打印到控制台。接下来,我们需要编译和运行这个测试程序。
首先,我们需要将测试程序的源代码保存为一个名为test.c
的文件。我们可以使用gcc编译器来编译该程序:
$ gcc -o test test.c
这将生成一个名为test
的可执行文件。接下来,需要将该可执行文件拷贝到Linux系统中运行。可以通过SSH等方式将文件传输到Linux系统中。在运行测试程序之前需要为测试程序添加可执行权限:
$ chmod +x test
现在,我们就可以运行测试程序了:
$ ./test
运行程序后,应该能够看到从/dev/hello
设备文件中读取的数据被打印到控制台上。
模块内打印的信息可以通过dmesg
命令进行打印,可以看到测试程序调用模块的过程。
六、相关知识
除了如何编写、编译和使用模块之外,还需要了解以下知识:
-
模块的依赖关系:在编写和使用模块时,需要考虑模块之间的依赖关系。如果一个模块依赖于另一个模块,则必须在前者之前将后者加载。否则,前者将无法正确运行。
-
模块的参数传递:有些模块需要在加载时传递参数。这些参数可以用于配置模块的行为或传递信息给模块。模块参数的传递方式有很多种,包括命令行参数、环境变量、配置文件等。
-
模块的版本管理:内核版本更新时,模块也需要相应更新。因此,需要了解如何为不同版本的内核编写适配的模块。
-
模块的调试:在开发模块时,可能会遇到各种各样的问题。因此,需要了解如何调试模块,例如使用 printk() 输出调试信息、使用 gdb 调试等。
-
模块的安全性:模块可以在内核空间执行,因此需要确保模块的安全性。内核提供了各种安全机制,例如模块签名验证、模块加载限制等。
相关文章:

【Linux驱动开发100问】什么是模块?如何编写和使用模块?
🥇今日学习目标:什么是Linux内核? 🤵♂️ 创作者:JamesBin ⏰预计时间:10分钟 🎉个人主页:嵌入式悦翔园个人主页 🍁专栏介绍:Linux驱动开发100问 什么是模块…...
Android 9.0 Recent列表不显示某个app
1.概述 在9.0的系统产品rom定制化开发中,在一些产品定制化需求中,也是有很多重要的功能实现的,比如在某些app的开发中 由于不想被杀掉,所以就不想出现在recent的列表中,因此就需要从recent的列表中,去掉这个app的显示,然后这里有 两种方法实现这个功能,一种是在app中就…...

深度学习之卷积神经网络学习笔记一
1. 引言深度学习是一系列算法的统称,包括卷积神经网络(CNN),循环神经网络(RNN),自编码器(AE),深度置信网络(DBN),生成对抗…...

黑盒测试的常用方法
这里我们先设置一个示例,后面的文章中会根据示例来进行讲解 假设有一个程序是判断一个整形数字是否属于1-100 目录 1.等价类法 2.边界值法 3.判定表法 4.场景设计法 5.错误猜测法 6.正交法 1.等价类法 概念:系统性的确定要输入的测试条件的方法可以看出概念非常抽象,那…...

操作系统笔记-第一章
文章目录操作系统概述1. 操作系统的概念1.1 操作系统的地位1.2 操作系统的作用1.3 操作系统的定义2. 操作系统的历史2.1 操作系统的产生2.1.1 手动操作阶段(20世纪40年代)2.1.2 批处理阶段(20世纪50年代)2.1.3 执行系统阶段&#…...
daillist
daillist #重要说明: #[1]任意两个配置参数之间必须以空格隔开,否则,拨号脚本无法识别。 #[2]Info格式说明:厂商名简称_制式_频段 #VID #PID #PORT_M #PORT_A #PORT_G #script_*99# #script_#777 #Info 05c6 9025 /dev/ttyUSB1 /dev/ttyUSB2 …...

vue中render函数的作用和参数(vue2中render函数用法)
render 函数是 Vue2.x 新增的一个函数、主要用来提升节点的性能,它是基于 JavaScript 计算。使用 Render 函数将 Template 里面的节点解析成虚拟的 Dom 。Vue 推荐在绝大多数情况下使用模板来创建 HTML。然而在一些场景中,需要 JavaScript 的完全编程能力…...

基于Istio的高级流量管理二(Envoy流量劫持、Istio架构、高级流量管理)
文章目录一、Envoy流量劫持机制(Iptables规则流转)1、流量出向劫持流程(1)envoy怎样劫持入向流量?(2)Envoy劫持到流量之后,干什么?(查询目的地)&a…...

Sharding-Springboot-mybatis-plus整合(三)-inline策略
Sharding-Springboot-mybatis-plus整合(三) 1.简介 本节目标,使用SpringBoot整合Sharding和Mybatis-Plus验证上节分片策略 从配置文件上看策略包括( inline、standard、complex、hint) 环境搭建以inline策略演示 …...

编码的基本概念
本专栏包含信息论与编码的核心知识,按知识点组织,可作为教学或学习的参考。markdown版本已归档至【Github仓库:information-theory】,需要的朋友们自取。或者公众号【AIShareLab】回复 信息论 也可获取。 文章目录信源编码分类前缀…...
函数指针与指针函数的区别
目录:一、函数指针1 函数类型2 函数指针(指向函数的指针)3 函数指针数组二.函数指针和指针函数比较1 定义不同2 写法不同3.用法不同三.函数指针做函数参数(回调函数)1 利用回调函数实现打印任意类型数据2 提供能够打印任意类型数组函数3 利用回调函数 提供查找功能四…...
死锁的四个必要条件以及如何避免死锁
死锁的四个必要条件以及如何避免死锁 一.什么是死锁?二.死锁的四个必要条件 1.互斥条件:2.请求与保持条件:3.不剥夺条件:4.循环等待条件: 三.如何避免死锁 1.破坏请求保持条件2.破坏不剥夺条件3.破坏循环等待条件 死锁的四个必要条件以及如…...

浏览器多线程到事件循环机制
浏览器与js运行机制 进程与线程 进程 进程是CPU分配资源的最小单位,它是一个可以自己独立运行且拥有自己资源空间的任务程序;包括程序以及程序所使用的内存及系统资源 线程 线程是CPU调度的最小单位,它就是程序中的一个执行流࿱…...

Lambda表达式的本质
一直想写一篇文章,来总结lambda表达式,但是之前感觉总结的不是特别到位,现在看了几篇文章和视频后,感觉对lambda表达式有了比较深刻的认识,现在进行记录总结如下: lambda表达式又叫做匿名函数,…...

类的加载过程(生命周期)
类的加载过程(生命周期) 一、装载:通过一个类的全限定名获取定义此类的二进制字节流将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构在内存中生成一个代表这个类的java.lang.Class对象(将字节码加载到内存中),作为…...

2023最新谷粒商城笔记之MQ消息队列篇(全文总共13万字,超详细)
MQ消息队列 其实队列JDK中本身就有,不过这种队列也只能单体服务可能会使用,一旦项目使用的分布式架构,那么一定还是需要用到一个消息中间件的。我们引入消息队列的原因就是对我们的页面相应速度再优化,让用户的体验更好ÿ…...

多变量线性回归模型
多变量线性回归模型 模型参数为n1维向量,此时模型公式为 hθ(x)θ0x0θ1x1θ2x2...θnxnh_{\theta}(x)\theta_{0}x_{0}\theta_{1}x_{1}\theta_{2}x_{2}...\theta_{n}x_{n} hθ(x)θ0x0θ1x1θ2x2...θnxn 可以简化为 hθ(x)θTXh_{\theta}(x)\th…...

php 基于ICMP协议实现一个ping命令
php 基于ICMP协议实现一个ping命令 网络协议是什么ICMP 协议什么是ICMP?ICMP 的主要功能ICMP 在 IPv4 和 IPv6 的封装Wireshark抓包ICMP 请求包分析PHP构建 ICMP 数据包php中的 pack & unpack 函数字节和字符packunpackICMP计算校验和步骤总结网络协议是什么 网络协议&…...

Java基本数据类型
1.概述 佛说,大千世界,无奇不有。在这个世界里,物种的多样性,遍地开花,同样,在Java的世界里,也有着异曲同工之妙,Java秉承面向对象的特性,必然少不了区分对象的类型&…...
English Learning - L2 语音作业打卡 Day2 2023.2.22 周三
English Learning - L2 语音作业打卡 Day2 2023.2.22 周三💌 发音小贴士:💌 当日目标音发音规则/技巧:🍭 Part 1【热身练习】🍭 Part2【练习内容】🍭【练习感受】🍓元音[ ɑː ]&…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...