Linux驱动开发:内核模块堆叠(1)

本文档简单说明内核模块堆叠的基本信息。
在Linux中内核模块的堆叠(module stacking)是指一个模块对另一个模块的依赖情况。
模块堆叠有利于模块间的代码复用和功能扩展:一个设备驱动可能依赖于一个提供通用功能的模块。


内核模块堆叠的关键点:

  1. 模块依赖关系:
  • 模块A可以使用模块B导出的符号(函数、变量等)
  • 当加载模块A时,内核会自动加载模块B(如果尚未加载)
  • 当模块B被卸载时,内核会检查是否有其他模块依赖于它,如果有则不允许卸载(除非使用强制卸载)
  1. 导出符号:
  • 模块可以通过EXPORT_SYMBOL()或EXPORT_SYMBOL_GPL()导出符号,供其他模块使用
  • 只有导出的符号才能被其他模块访问
  1. 模块引用计数:
  • 每个模块都有一个引用计数,记录当前有多少其他模块正在使用它
  • 当引用计数不为零时,模块不能被卸载
  1. 自动加载:
  • 可以通过request_module()函数在运行时自动加载另一个模块
  1. 模块堆叠的注意事项:
  • 避免循环依赖
  • 注意模块加载顺序:卸载时,必须先卸载依赖其他模块的模块,然后才能卸载被依赖的模块
  1. 查看模块依赖关系:
  • 使用lsmod命令可以查看已加载模块的依赖关系
  1. 模块别名和软依赖:
  • 可以在模块中使用MODULE_SOFTDEP()声明软依赖,提示在加载该模块之前先加载其他模块

示例:
假设我们有两个模块:module_a和module_b,其中module_a依赖于module_b导出的一个函数
module_b.c通过EXPORT_SYMBOL(module_b_exported_function);导出module_b_exported_function

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

static int __init module_b_init(void)
{
    printk(KERN_INFO "Module B initialized\n");
    return 0;
}

static void __init module_b_exit(void)
{
    printk(KERN_INFO "Module B exiting\n");
}

// 导出一个函数
void module_b_exported_function(void)
{
    printk(KERN_INFO "Module B exported function called\n");
}
EXPORT_SYMBOL(module_b_exported_function);

module_init(module_b_init);
module_exit(module_b_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Module B providing a function for other modules");

module_a.c使用module_b的功能 extern void module_b_exported_function(void);

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

// 声明来自module_b的函数
extern void module_b_exported_function(void);

static int __init module_a_init(void)
{
    printk(KERN_INFO "Module A initialized\n");
    // 调用module_b导出的函数
    module_b_exported_function();
    return 0;
}

static void __init module_a_exit(void)
{
    printk(KERN_INFO "Module A exiting\n");
}

module_init(module_a_init);
module_exit(module_a_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Module A using Module B's function");

使用时,可使用insmod/modprobe加载module_a;使用modprobe时会自动处理依赖关系

posted @ 2026-02-03 17:49  bitwoods  阅读(1)  评论(0)    收藏  举报