内核模块基本概念
作用
解决linux内核可扩展性和可维护性相对较差的缺陷
现代内核派系
宏内核:关键功能和服务功能均在内核空间提供
- 运行效率高
- 扩展性较差
微内核:内核空间只提供关键功能,服务功能在用户空间提供
- 运行效率较低
- 安全性、扩展性较高
内核模块加载/卸载
-
使用insmod命令加载
-
使用rmmod命令卸载
内核模块入口/出口
- module_init():加载模块式该函数自动执行,进行初始化操作
- module_exit():卸载模块时函数自动执行,进行清理操作
内核模块信息声明
- MODULE_LICENSE():表示模块代码接受的软件许可协议,Linux内核遵循GPL V2开源协议,内核模块与linux内核保持一致即可。
- MODULE_AUTHOR():描述模块的作者信息
- MODULE_DESCRIPTION():对模块的简单介绍
- MODULE_ALIAS():给模块设置一个别名
内核模块实验1
实验环境
- 开发板烧录好Debian镜像
- 启动开发板,搭建好nfs客户端,挂载共享文件夹
- 获取Debian镜像的内核源码并编译
编译4.19.71版本内核
内核模块的功能需要依赖内核提供的各种底层接口
1.下载linux内核源码
github:
git clone https://github.com/Embedfire/ebf-buster-linux.git
gitee:
git clone https://gitee.com/Embedfire/ebf-buster-linux.git
2.安装必要环境工具库
sudo apt install make gcc-arm-linux-gnueabihf gcc bison flex libssl-dev dpkg-dev lzop
3.一键编译内核
sudo ./make_deb.sh
4.获取编译出来的内核相关文件
/home/pi/build
内核模块头文件
- #include <linux/module.h>:包含内核模块信息声明的相关函数
- #include <linux/init.h>:包含了 module_init()和 module_exit()函数的声明
- #include <linux/kernel.h>:包含内核提供的各种函数,如printk
内核模块打印函数
-
printf:glibc实现的打印函数,工作于用户空间
-
printk:内核模块无法使用glibc库函数,内核自身实现的一个类printf函数,但是需要指定打印等级。
- #define KERN_EMERG "<0>" 通常是系统崩溃前的信息 - #define KERN_ALERT "<1>" 需要立即处理的消息 - #define KERN_CRIT "<2>" 严重情况 - #define KERN_ERR "<3>" 错误情况 - #define KERN_WARNING "<4>" 有问题的情况 - #define KERN_NOTICE "<5>" 注意信息 - #define KERN_INFO "<6>" 普通消息 - #define KERN_DEBUG "<7>" 调试信息
查看当前系统printk打印等级:cat /proc/sys/kernel/printk
- 当前控制台日志级别
- 默认消息日志级别
- 最小的控制台级别
- 默认控制台日志级别
打印内核所有打印信息:dmesg
- 内核log缓冲区大小有限制,缓冲区数据可能被冲掉
Makefile分析
-
KERNEL_DIR:指向linux内核具体路径
-
export:导出变量给子Makefile使用
-
obj-m := <模块名>.o:定义要生成的模块
-
$(MAKE):Makefile的默认变量,值为make
-
选项”-C”:让make工具跳转到linux内核目录下读取顶层Makefile
-
M=:表示内核模块源码目录
-
$(CURDIR):Makefile默认变量,值为当前目录所在路径
-
make modules:执行Linux顶层Makefile的伪目标,它实现内核模块的源码读取并编译为.ko文件
编译内核模块
make
把生成的内核模块拷贝到nfs共享目录
make copy
开发板加载内核模块
insmod xxx.ko
内核模块实验2
mobaxterm设置窗口行数、列数
Linux终端窗口
- 查询终端窗口的行列数:stty size
- 设置终端窗口列数:stty cols xx
- 设置终端窗口行数:stty rows xx
mobaxterm窗口
- 右击会话窗口,选择“edit session ”->“Terminal settings”->“Terminial font settings”->“Terminal size”
模块参数
根据不同应用场合给内核模块传递不同参数,提高内核模块灵活性
- 定义一个常见变量
- 使用module_param宏把传参值赋给变量
module_param(name, type, perm)
- name:参数名
- type:参数类型,如int、byte、bool、charp…
- perm:读写权限
- 不允许设置可执行权限
- 在“/sys/module/模块名/parameters”目录下,会生成该参数对应的文件名
符号共享
内核模块可以共享导出的符号表
- 变量共享
- 函数共享
EXPORT_SYMBOL(sym)
- sym:变量名或者函数名
查看符号表
cat /proc/kallsyms | grep xxx
Makefile修改
- 有依赖关系的模块,放在一起进行编译
- clean伪目标增加清除共享文件夹指令
模块手动加载
- 加载时,必须先加载相关依赖模块
- 卸载时,顺序相反
模块自动加载
-
所有内核模块统一放到"/lib/modules/内核版本"目录下
cp *.ko /lib/modules/内核版本
-
建立模块依赖关系:
depmod -a
-
查看模块依赖关系
cat /lib/modules/内核版本/modules.dep
-
加载模块及其依赖模块文章来源:https://www.toymoban.com/news/detail-808934.html
modprobe xxx
-
卸载模块及其依赖模块文章来源地址https://www.toymoban.com/news/detail-808934.html
modprobe -r xxx
到了这里,关于IMX6LL|内核模块的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!