【Linux驱动开发 ---- 2_深入理解内核模块】

发布于:2025-06-19 ⋅ 阅读:(16) ⋅ 点赞:(0)

Linux驱动开发 ---- 2_深入理解内核模块

学习目标
  • 理解Linux内核模块的基本概念和工作原理。
  • 掌握模块的加载(insmod)、卸载(rmmod)和参数传递。
  • 编写并测试一个简单的内核模块。
时间安排建议
  • 理论学习(1-2小时):学习内核模块的基础知识。
  • 实践(1小时):编写、编译和测试内核模块。

理论学习

1. 什么是内核模块?
  • 内核模块是Linux内核的可加载扩展,可以动态加载到内核中,无需重启系统。
  • 优点:提高灵活性,减少内核体积。
  • 文件后缀:.ko(Kernel Object)。
  • 示例:USB驱动、网络驱动通常以模块形式存在。
2. 模块加载与卸载
  • insmod:加载模块到内核。
    • 用法:insmod module.ko [参数]
  • rmmod:卸载模块。
    • 用法:rmmod module_name
  • lsmod:查看已加载的模块。
  • 模块参数:可以在加载时传递参数给模块。
    • 示例:insmod my_module.ko my_param=5
3. 内核模块开发基础
  • 基本结构:
    • 初始化函数(加载时调用)。
    • 退出函数(卸载时调用)。
  • 常用头文件:<linux/module.h><linux/kernel.h>
  • 编译:需要内核源码和Makefile

实践任务

任务1:准备开发环境
  1. 检查内核版本

    uname -r
    
    • 示例输出:5.15.0-73-generic(Ubuntu 22.04默认版本)。
      在这里插入图片描述
  2. 安装内核头文件和开发工具

    sudo apt install linux-headers-$(uname -r) build-essential
    

在这里插入图片描述

  1. 创建工作目录
    mkdir ~/kernel_modules && cd ~/kernel_modules
    
    在这里插入图片描述
任务2:编写简单内核模块
  1. 创建文件hello_module.c
    nano hello_module.c
    
  2. 输入以下代码:
#include <linux/module.h>    // 内核模块必需头文件
#include <linux/kernel.h>    // 提供printk等内核函数
#include <linux/init.h>      // 定义模块初始化和退出宏

// 定义一个模块参数
static int my_param = 0;
module_param(my_param, int, S_IRUGO); // S_IRUGO表示参数可读

// 模块初始化函数,加载时调用
static int __init hello_init(void) {
    printk(KERN_INFO "Hello, World! Parameter: %d\n", my_param);
    return 0; // 返回0表示成功
}

// 模块退出函数,卸载时调用
static void __exit hello_exit(void) {
    printk(KERN_INFO "Goodbye, World!\n");
}

// 注册初始化和退出函数
module_init(hello_init);
module_exit(hello_exit);

// 模块元信息
MODULE_LICENSE("GPL");           // 许可证
MODULE_AUTHOR("Your Name");      // 作者
MODULE_DESCRIPTION("A simple hello world module"); // 描述

在这里插入图片描述

任务3:编写Makefile
  1. 创建文件Makefile

    nano Makefile
    
  2. 输入以下内容:

    obj-m += hello_module.o
    
    all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
    
    clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
    
任务4:编译和测试模块
  1. 编译模块

    make
    
    • 输出文件:hello_module.ko
  2. 加载模块

    sudo insmod hello_module.ko my_param=42
    
  3. 查看日志

    dmesg | tail
    
    • 预期输出:Hello, World! Parameter: 42
  4. 检查已加载模块

    lsmod | grep hello
    
  5. 卸载模块

    sudo rmmod hello_module
    
  6. 再次查看日志

    dmesg | tail
    
    • 预期输出:Goodbye, World!
任务5:清理环境
make clean

代码详解

hello_module.c详解
  • #include <linux/module.h>:提供模块相关宏和函数。
  • printk(KERN_INFO ...):内核日志函数,KERN_INFO表示信息级别,输出到/var/log/kern.logdmesg
  • module_param:定义可传递的参数,my_param是整数类型,S_IRUGO表示全局可读。
  • __init__exit:标记初始化和退出函数,__init函数在加载后释放内存。
  • MODULE_LICENSE("GPL"):声明模块遵循GPL许可证,避免内核污染警告。
Makefile详解
  • obj-m += hello_module.o:指定目标模块。
  • -C /lib/modules/...:指向内核源码目录。
  • M=$(PWD):指定当前目录为模块构建路径。

注意事项

  • 权限问题:加载模块需要sudo,否则会提示权限不足。
  • 日志查看dmesg可能包含大量信息,用tail筛选最新日志。
  • 内核版本匹配:确保linux-headers版本与当前内核一致(uname -r)。
  • 实践巩固:尝试修改my_param值或日志内容,重新编译测试。

总结

完成以上内容后,您将:

  • 理解内核模块的作用和基本结构。
  • 掌握模块的编写、编译、加载和卸载。
  • 成功运行一个打印“Hello, World!”的模块,并传递参数。

网站公告

今日签到

点亮在社区的每一天
去签到