Linux init_module与finit_module区别
Linux init_module和finit_module的区别
init_module
和 finit_module
都是 Linux 内核中用于加载内核模块的系统调用,但它们在数据传递方式和效率上有显著区别:
1. init_module
- 原型:
int init_module(void *module_image, unsigned long len, const char *param_values);
- 工作方式:
- 需要用户空间程序预先将整个内核模块文件(
.ko
)读入内存。 - 通过指针
module_image
将模块数据传递给内核。 len
指定内存中模块数据的大小。param_values
传递模块参数(字符串格式,如"debug=1"
)。
- 需要用户空间程序预先将整个内核模块文件(
- 缺点:
- 消耗用户态内存(需完整加载模块)。
- 额外内存拷贝(用户态→内核态)。
2. finit_module
- 原型:
int finit_module(int fd, const char *param_values, int flags);
- 工作方式:
- 通过文件描述符
fd
传递模块(需提前打开模块文件)。 - 内核直接从文件读取数据,无需用户态缓冲。
flags
支持额外选项(如忽略版本检查):MODULE_INIT_IGNORE_MODVERSIONS
MODULE_INIT_IGNORE_VERMAGIC
- 通过文件描述符
- 优点:
- 节省用户态内存(避免预加载文件)。
- 减少数据拷贝(内核直接读文件)。
- 更高效(尤其对大模块)。
关键区别总结
特性 | init_module | finit_module |
---|---|---|
数据来源 | 用户态内存缓冲区 | 文件描述符(直接访问文件) |
内存效率 | 低(需预加载文件到内存) | 高(内核直接读取文件) |
参数传递 | param_values 字符串 |
param_values 字符串 + flags |
额外功能 | 无 | 支持版本检查忽略等标志 |
引入版本 | 传统方式(早期内核) | Linux 3.8+ |
使用场景建议
**优先使用
finit_module
**:
适用于模块以文件形式存在(如标准.ko
文件),效率更高,代码更简洁。1
2
3int fd = open("module.ko", O_RDONLY);
finit_module(fd, "debug=1", MODULE_INIT_IGNORE_VERMAGIC);
close(fd);使用
init_module
的场景:
模块数据动态生成(如网络下载或内存构建),无法通过文件描述符访问。1
2void *module_data = load_module_from_network();
init_module(module_data, data_size, "debug=1");
其他注意事项
- 权限要求:
两者均需CAP_SYS_MODULE
能力(通常需 root 权限)。 - 错误处理:
- 失败时返回
-1
,需检查errno
(如ENOMEM
、EINVAL
)。
- 失败时返回
- 模块卸载:
统一使用delete_module()
系统调用卸载模块。
通过优先选择 finit_module
,可提升加载效率并降低资源占用,是现代化驱动开发的推荐方式。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Helloeuler!