Linux内核模块

目录

模块(Module)

加载模块

卸载模块

查看模块信息

Linux内核模块程序结构

1、模块加载函数

2、模块卸载函数

3、模块许可证声明

4、模块参数(可选)

5、模块导出符号(可选)

6、模块作者等信息声明(可选)

模块使用计数

7、模块的编译


模块(Module)

Linux内核的整体架构本就非常庞大, 其包含的组件也非常多。 而我们怎样把需要的部分都包含在内核中呢?
一种方法是把所有需要的功能都编译到Linux内核中。 这会导致两个问题:

1、生成的内核会很大

2、如果我们要在现有的内核中新增或删除功能, 将不得不重新编译内核。


有没有另一种机制可使得编译出的内核本身并不需要包含所有功能, 而在这些功能需要被使用的时候, 其对应的代码被动态地加载到内核中呢?
Linux提供了这样的机制, 这种机制被称为模块(Module) 。 模块具有这样的特点:

1、模块本身不被编译入内核映像, 从而控制了内核的大小。
2、模块一旦被加载, 它就和内核中的其他部分完全一样。
 

加载模块

简单命令:iinsmod modName

模块依赖命令:modprobe (加载模块及其依赖的其他模块)

卸载模块

简单命令:rmmod modName

模块依赖命令:modprobe -r modName(卸载模块及其依赖的其他模块)

查看模块信息

modinfo  modName

信息包括模块作者、 模块的说明、 模块所支持的参数以及vermagic
 

 

Linux内核模块程序结构

1、模块加载函数

当通过insmod或modprobe命令加载内核模块时, 模块的加载函数会自动被内核执行, 完成本模块的相关初始化工作。

static int _ _init initialization_function(void)
{
/* 初始化代码 */
}
module_init(initialization_function);


2、模块卸载函数

当通过rmmod命令卸载某模块时, 模块的卸载函数会自动被内核执行, 完成与模块卸载函数相反的功能。

static void _ _exit cleanup_function(void)
{
/* 释放代码 */
}
module_exit(cleanup_function);

3、模块许可证声明

许可证(LICENSE) 声明描述内核模块的许可权限, 如果不声明LICENSE, 模块被加载时, 将收到内核被污染(Kernel Tainted) 的警告。
在Linux内核模块领域, 可接受的LICENSE包括“GPL”、 “GPL v2”、 “GPL and additional rights”、 “Dual BSD/GPL”、 “Dual MPL/GPL”和“Proprietary”

4、模块参数(可选)

模块参数是模块被加载的时候可以传递给它的值, 它本身对应模块内部的全局变量。

static char *book_name = "dissecting Linux Device Driver";
module_param(book_name, charp, S_IRUGO);
static int book_num = 4000;
module_param(book_num, int, S_IRUGO);

调用命令:

insmod book.ko book_name='GoodBook' book_num=5000

5、模块导出符号(可选)

内核模块可以导出的符号(symbol, 对应于函数或变量) , 若导出, 其他模块则可以使用本模块中的变量或函数。

EXPORT_SYMBOL(符号名);
EXPORT_SYMBOL_GPL(符号名);

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

int add_integar(int a, int b)
{
return a + b;
}
EXPORT_SYMBOL_GPL(add_integar);

int sub_integar(int a, int b)
{
    return a - b;
}
EXPORT_SYMBOL_GPL(sub_integar);
MODULE_LICENSE("GPL v2");

导出的符号可以被其他模块使用, 只需使用前声明一下即可

6、模块作者等信息声明(可选)

MODULE_AUTHOR(author);
MODULE_DESCRIPTION(description);
MODULE_VERSION(version_string);
MODULE_DEVICE_TABLE(table_info);
MODULE_ALIAS(alternate_name);

模块使用计数

用于增加模块使用计数,若返回为0,表示调用失败,希望使用的模块没有被加载或正在被卸
载中。

int try_module_get(struct module *module);

用于减少模块使用计数。

void module_put(struct module *module);

7、模块的编译

使用Makefile进行编译

KVERS = $(shell uname -r)
# Kernel modules
obj-m += hello.o
# Specify flags for the module compilation.
#EXTRA_CFLAGS=-g -O0
build: kernel_modules
kernel_modules:
make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
clean:
make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值