IMX6LL|内核模块

内核模块基本概念

作用

解决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
    
  • 加载模块及其依赖模块

    modprobe xxx
    
  • 卸载模块及其依赖模块

    modprobe -r xxx
    
相关推荐
叶北辰CHINA26 分钟前
nginx反向代理,负载均衡,HTTP配置简述(说人话)
linux·运维·nginx·http·云原生·https·负载均衡
不惑_43 分钟前
在 Ubuntu 安装 Python3.7(没有弯路)
linux·运维·ubuntu
嵌入式杂谈1 小时前
STM32中断编程详解:配置外部中断和中断服务例程
stm32·单片机·嵌入式硬件
光子物联单片机2 小时前
传感器模块编程实践(三)舵机+超声波模块融合DIY智能垃圾桶模型
stm32·单片机·嵌入式硬件·mcu
玉树临风江流儿2 小时前
Linux驱动开发(速记版)--设备模型
linux·驱动开发
杰哥在此2 小时前
Python知识点:如何使用Multiprocessing进行并行任务管理
linux·开发语言·python·面试·编程
嵌入式杂谈4 小时前
STM32中断编程指南:NVIC和中断优先级
stm32·单片机·嵌入式硬件
枫叶丹44 小时前
【在Linux世界中追寻伟大的One Piece】进程信号
linux·运维·服务器
刻词梨木4 小时前
ubuntu中挂载点内存不足,分配不合理后使用软链接的注意事项
linux·运维·ubuntu
灯火不休ᝰ5 小时前
[win7] win7系统的下载及在虚拟机中详细安装过程(附有下载文件)
linux·运维·服务器