1、Linux驱动开发:模块_加载卸载

目录

🍅点击这里查看所有博文

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

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

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

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

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

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

前言

  一个基础模块的源代码,应有c文件,h文件(可选)和makefile文件构成 。

C文件

  c文件中除了必要的函数申明以及头文件导入外,还要分别为模块声明载入函数和销毁函数。载入函数使用module_init声明,当模块被加载进入内核的时候该函数会被调用。销毁函数使用module_exit声明,当从内核中移除模块时该函数会被调用。

  宏MODULE_LICENSE宏用于声明此模块的许可证,宏MODULE_AUTHOR的用于声明内核模块的作者。

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("PD");
static int hello_init(void)
{printk(KERN_SOH"hello_init \n");return 0;
}
static void hello_exit(void)
{printk("hello_exit \n");return;
}
module_init(hello_init); //insmod
module_exit(hello_exit);//rmmod

  从2.4.10版本内核开始,模块必须通过MODULE_LICENSE宏声明此模块的许可证,否则在加载此模块时,会收到内核被污染 “kernel tainted” 的警告。从linux/module.h文件中可以看到,被内核接受的有意义的许可证有 “GPL”,“GPL v2”,“GPL and additional rights”,“Dual BSD/GPL”,“Dual MPL/GPL”,“Proprietary”。

/** The following license idents are currently accepted as indicating free* software modules**	"GPL"				[GNU Public License v2 or later]*	"GPL v2"			[GNU Public License v2]*	"GPL and additional rights"	[GNU Public License v2 rights and more]*	"Dual BSD/GPL"			[GNU Public License v2*					 or BSD license choice]*	"Dual MIT/GPL"			[GNU Public License v2*					 or MIT license choice]*	"Dual MPL/GPL"			[GNU Public License v2*					 or Mozilla license choice]** The following other idents are available**	"Proprietary"			[Non free products]** There are dual licensed components, but when running with Linux it is the* GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL* is a GPL combined work.** This exists for several reasons* 1.	So modinfo can show license info for users wanting to vet their setup*	is free* 2.	So the community can ignore bug reports including proprietary modules* 3.	So vendors can do likewise based on their own policies*/
#define MODULE_LICENSE(_license) MODULE_INFO(license, _license)

makefile文件

  此makefile可作为一个通用示例。

ifneq ($(KERNELRELEASE),)
$(info "makebuild2")
obj-m:=hello.o
else
KDIR :=/lib/modules/$(shell uname -r)/build
PWD  :=$(shell pwd)
all:$(info "makebuild1")make -C $(KDIR) M=$(PWD) modules
clean:rm -f *.ko *.o *.mod.o *.symvers *.cmd  *.mod.c *.orderrm -rf .*.cmd .*.mk .*/
endif

  在编译模块运行make命令时。首先由于KERNELRELEASE变量不存在,会直接进入else分支,执行内核modules的make流程。

root@ubuntu:# make
"makebuild1"
make -C /lib/modules/4.15.0-142-generic/build M=/home/peng/Desktop/driver/example/1_module modules
make[1]: Entering directory '/usr/src/linux-headers-4.15.0-142-generic'

  第二步再次从头开始重新执行该makefile,由于第一步中已经指定了内核模块编译,此时KERNELRELEASE不为空,会进入到ifneq分支,完成*.o的生成。

"makebuild2"CC [M]  /home/peng/Desktop/driver/example/1_module/hello.oBuilding modules, stage 2.

  完成hello.o的编译后,最后一步会执行一个转化和链接的操作。该makefile被再次调用。将*.o转化为*.mod.o,最后完成内核模块的链接生成*.ko

"makebuild2"MODPOST 1 modulesCC      /home/peng/Desktop/driver/example/1_module/hello.mod.oLD [M]  /home/peng/Desktop/driver/example/1_module/hello.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.15.0-142-generic'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aHqKKr91-1690035344898)(/imgs/2023-07-22/S3NYRHyl7RwQ6RJc.png)]

加载卸载

  加载模块前建议先清除dmesg的日志信息。否则影响调试

root@ubuntu:$ dmesg -c

  使用insmod加载模块,加载完成可通过dmesg查看载入函数的日志打印,也可以通过lsmod查看模块是否被正常加载。

root@ubuntu:# insmod ./hello.ko
root@ubuntu:# dmesg
[ 6891.682070] hello_init 
root@ubuntu:# lsmod | grep hello
hello                  16384  0

  使用rmmod卸载模块,卸载完成可通过dmesg查看卸载函数的日志打印,也可以通过lsmod查看模块是否被正常卸载。

root@ubuntu:# rmmod ./hello.ko
root@ubuntu:# dmesg
[ 6891.682070] hello_init 
[ 7087.613847] hello_exit 
root@ubuntu:# lsmod | grep hello

常用操作

  • lsmod:显示模块
  • insmod/rmmod:安装/卸载模块
  • dmesg -c:清除log信息
  • dmesg:打印log信息

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/7179.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

github上下载的vscode extension报找不到“vscode“模块的问题

问题来自于下载的 vscode 扩展源代码包 import * as vscode from "vscode"; 有问题的是这句&#xff0c;找不到 vscode 模块&#xff0c;错误代码 2307 主要是因为下载的源码工程里&#xff0c;没有 node_modules 这个文件夹&#xff0c;因为它本来就是需要被忽略…

97、Kafka的性能好在什么地方

Kafka的性能好在什么地方 一、顺序写二、零拷贝三、额外补充 kafka不基于内存&#xff0c;而是硬盘存储&#xff0c;因此消息堆积能力更强 一、顺序写 顺序写 : 利用磁盘的顺序访问速度可以接近内存&#xff0c;kafka的消息都是append操作&#xff0c;partition是有序的&#…

(数据结构)哈夫曼编码实现(C语言)

(数据结构)哈夫曼编码实现&#xff08;C语言&#xff09; 哈夫曼的编码:从一堆数组当中取出来最小的两个值&#xff0c;按照左下右大的进行绘制&#xff0c;将两个权值之和&#xff0c;放入队列当中&#xff0c;然后再进行取出两个小的&#xff0c;以此类推&#xff0c;直到全部…

VuePress在生产环境跳转子页报错 Failed to execute ‘appendChild‘ on ‘Node‘

记录一个使用VuePress时遇到的问题 使用VuePress做了一个文档网页&#xff0c;在开发环境的时候一切正常&#xff0c;但是发布到生产环境后&#xff0c;直接跳转二级页面会报错Failed to execute appendChild on Node 比如主页是http://sun/docs/.vuepress/dist/index.html#/…

SwiftUI-基础

应用入口 Main函数与App结构体的绑定&#xff0c;遵循App协议 main struct BaseApp: App {var body: some Scene {WindowGroup {ContentView()}} } 兼容UIApplicationDelegate main struct BasicApp: App {UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate…

【C语言项目】三子棋

文章目录 项目思路一、分文件进行创建二、进入游戏前的目录2.1 目录的功能&#xff1a;2.2 目录界面&#xff1a;2.3 选择进入或退出游戏2.4 多次重玩功能 三、画出棋盘3.1 写出棋子3.2 初始化棋盘3.2 画出棋盘的框架3.3 代码实现 四、玩家落子4.1 落子逻辑4.2具体情况分类讨论…

抖斗音直播间评论引流助手,支持直播间喊话+视频评论区喊话=到指定直播间引流精准粉丝【永久脚本+详细教程】

如果你觉得直播间发言手动太麻烦了&#xff0c;或许这个自动工具能帮到你&#xff01; 1.开始运行前&#xff0c;需要手动去打开打开直播间或者视频评论区&#xff0c;再运行脚本。 2.脚本就是模拟人工操作&#xff0c;在相应的APP里进行评论&#xff0c;无突破APP限制功能。…

[USACO14DEC] Marathon G

洛谷[USACO14DEC] Marathon G 题目大意 Bessie \text{Bessie} Bessie设计了一条马拉松路线&#xff0c;有 N N N个点。 Bessie \text{Bessie} Bessie有 q q q次操作&#xff0c;每次操作是修改或询问。每次修改会修改一个点的坐标&#xff0c;每次询问是选手跑过一条子路径的时…

阿里云ACK的etcd证书过期手工升级操作

一.问题现象 阿里云ACK的etcd证书过期&#xff0c;通过图形化界面升级提示升级失败&#xff0c;考虑通过脚本的方式升级ETCD相关的证书。由于在前期做类似的升级ETCD证书失败导致整个集群业务出现访问异常&#xff0c;所有在升级之前做好对应的备份操作是很有必要的 二.前期准…

【Kubernetes运维篇】ingress-nginx实现业务灰度发布详解

文章目录 一、理论&#xff1a;实现灰度发布的几种场景1、场景一&#xff1a;将新版本灰度给部分用户2、场景二&#xff1a;按照比例流程给新版本3、实现灰度发布字段解释 二、实践&#xff1a;1、实验前提环境2、基于Request Header(请求头)进行流量分割3、基于Cookie进行流量…

93.qt qml-自定义Table优化(新增:水平拖拽/缩放自适应/选择使能/自定义委托)

之前我们更新了90.qt qml-Table表格组件(支持表头表尾固定/自定义颜色/自定义操作按钮/排序)_qml 表格_诺谦的博客-CSDN博客 但是一直没出源码,是因为该demo还存在问题,那就是表头表尾固定下,如果是半透明状态下,会看到表头表尾固定后的内容,所以只能重构代码,不能使用重…

Vue3组合式API+TypeScript写法入门

文章目录 前言1.reactive2.ref3.props4.computed5.emit6.watch总结 前言 参考Vue3官网. 本篇以组合式API为例, 但不包含setup语法糖式写法. 原本打算结合class-component, Vue3不推荐就不用了: OverView|Vue Class Component. 而且是不再推荐基于类的组件写法, 推荐单文件组件…

Android App 持续集成性能测试:启动流量

目录 前言&#xff1a; get app UID 获取流量数据 获得启动流量数据 总结 前言&#xff1a; Jenkins 是一种开源的持续集成工具&#xff0c;可以帮助我们更加方便地进行软件开发和测试工作。通过 API 远程管理 Jenkins 可以帮助我们更加方便地进行 Jenkins 的配置和管理工…

react实现路由跳转动画

下载插件 npm i react-transition-group 配置路由 import { createBrowserRouter as ReactRouter,Navigate } from "react-router-dom";import App from ../App.js import Login from "../view/login.js"; import Home from "../home.js"; co…

了解 3DS MAX 3D摄像机跟踪设置:第 4 部分

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 项目设置 步骤 1 打开“后效”。 打开后效果 步骤 2 转到合成>新合成以创建新合成。 将“宽度”和“高度”值分别设置为 1280 和 720。将帧速率设置为 25&#xff0c;将持续时间设置为 12 秒。单…

Go基本数据类型及内置函数(一文稳定基础)

文章目录 1. 基础数据类型2.内置函数3.函数4.列表操作及for循环5.原子性操作6.通道7.协程与并发安全8.定时器 1. 基础数据类型 1. bool&#xff1a;布尔类型&#xff0c;只有 true 和 false 两个值。var test2 bool true2. string&#xff1a;字符串类型&#xff0c;表示一组字…

微服务网关

1.网关是如何演化来的&#xff0c;在微服务中有什么作用&#xff1f; 随着单体架构转化为微服务架构的时候&#xff0c;由一个后台服务由一个单一的服务变成了多个微服务&#xff0c;前端应用需要调用多个服务的接口&#xff0c;为了解决这个问题&#xff0c;网关就产生了。网…

【LeetCode】55.跳跃游戏

题目 给定一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标。 示例 1&#xff1a; 输入&#xff1a;nums [2,3,1,1,4] 输出&#xff1a;true 解释&#xff1a;可以…

一个月学通Python(二十六):Django使用缓存

专栏介绍 结合自身经验和内部资料总结的Python教程,每天3-5章,最短1个月就能全方位的完成Python的学习并进行实战开发,学完了定能成为大佬!加油吧!卷起来! 全部文章请访问专栏:《Python全栈教程(0基础)》 文章目录 专栏介绍使用缓存Django项目接入Redis为视图提供缓…

Flask 文件上传,删除上传的文件

目录结构 app.py from flask import Flask, request, render_template, redirect, url_for import osapp Flask(__name__) BASE_DIR os.getcwd() UPLOAD_FOLDER os.path.join(BASE_DIR, testfile)app.route(/) def home():files os.listdir(UPLOAD_FOLDER)return render_t…