Linux驱动开发:1、模块_加载卸载
目录
随着自己工作的进行,接触到的技术栈也越来越多。给我一个很直观的感受就是,某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了,只有经常会用到的东西才有可能真正记下来。存在很多在特殊情况下有一点用处的技巧,用的不多的技巧可能一个星期就忘了。
想了很久想通过一些手段把这些事情记录下来。也尝试过在书上记笔记,这也只是一时的,书不在手边的时候那些笔记就和没记一样,不是很方便。
很多时候我们遇到了问题,一般情况下都是选择在搜索引擎检索相关内容,这样来的也更快一点,除非真的找不到才会去选择翻书。后来就想到了写博客,博客作为自己的一个笔记平台倒是挺合适的。随时可以查阅,不用随身携带。
同时由于写博客是对外的,既然是对外的就不能随便写,任何人都可以看到。经验对于我来说那就只是经验而已,公布出来说不一定我的一些经验可以帮助到其他的人。遇到和我相同问题时可以少走一些弯路。
既然决定了要写博客,那就只能认真去写。不管写的好不好,尽力就行。千里之行始于足下,一步一个脚印,慢慢来
,写的多了慢慢也会变好的。权当是记录自己的成长的一个过程,等到以后再往回看时,就会发现自己以前原来这么菜😂。
本系列博客所述资料均来自互联网资料
,并不是本人原创(只有博客是自己写的)。出于热心,本人将自己的所学笔记整理并推出相对应的使用教程,方面其他人学习。为国内的物联网事业发展尽自己的一份绵薄之力,没有为自己谋取私利的想法
。若出现侵权现象,请告知本人,本人会立即停止更新,并删除相应的文章和代码。
前言
一个基础模块的源代码,应有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 *.order
rm -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.o
Building modules, stage 2.
完成hello.o的编译后,最后一步会执行一个转化和链接的操作。该makefile被再次调用。将*.o
转化为*.mod.o
,最后完成内核模块的链接生成*.ko
"makebuild2"
MODPOST 1 modules
CC /home/peng/Desktop/driver/example/1_module/hello.mod.o
LD [M] /home/peng/Desktop/driver/example/1_module/hello.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.15.0-142-generic'
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cYaB26gb-1690343130822)(https://raw.githubusercontent.com/chenxiahuaxu/stackedit-app-data-img/master/2023/07/22/1.%E6%A8%A1%E5%9D%97_%E5%8A%A0%E8%BD%BD%E5%8D%B8%E8%BD%BD/13qSi7ijnkTc7f2S.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信息
那么本篇博客就到此结束了,这里只是记录了一些我个人的学习笔记,其中存在大量我自己的理解。文中所述不一定是完全正确的,可能有的地方我自己也理解错了。如果有些错的地方,欢迎大家批评指正。如有问题直接在对应的博客评论区指出即可,不需要私聊我。我们交流的内容留下来也有助于其他人查看,说不一定也有其他人遇到了同样的问题呢😂。
更多推荐
所有评论(0)