linux - 内核模块如何卸载自身而不在内核日志中产生错误?

标签 linux linux-kernel kernel-module

我制作了一个在加载时打印 GDT 和 IDT 的简单模块。完成工作后,就不再需要它了,可以将其卸载。但如果它返回一个负数以停止加载,insmod 会报错,并且会在内核日志中记录一条错误消息。

内核模块如何优雅地卸载自身?

最佳答案

据我所知,使用标准内核是不可能的(您可以按照我在下面描述的那样修改模块加载器核心,但这可能不是一件值得依赖的好事)。

好的,所以我查看了模块加载和卸载代码 ( kernel/module.c ) 以及非常可疑的名称 module_put_and_exit 的几个用户.似乎没有内核模块可以执行您想要执行的操作。它们都在模块的上下文中启动 kthread,然后在完成某些操作后终止 kthread(它们不会自动卸载模块)。

不幸的是,执行大量模块卸载的函数 (free_module) 是在 kernel/module.c 中静态定义的。据我所知,没有从模块中调用 free_module 的导出函数。我觉得这可能有一些原因(尝试从自身卸载模块很可能会导致页面错误,因为需要释放包含模块代码的页面)。虽然这可能可以通过制作一个 noreturn 函数来解决,该函数只是在防止当前(无效)任务再次运行(或只是运行 do_exit)。

还有一点要问:你确定要这样做吗?您为什么不制作一个 shell 脚本来加载和卸载模块并收工呢?根据我的喜好,自动卸载模块可能有点太接近天网了。

编辑:如果您不介意修改模块加载器核心,我已经尝试了一些,并找到了一种方法来执行此操作。将此函数添加到 kernel/module.c,并对 include/linux/module.h 进行必要的修改:

/* Removes a module in situ, from within the module itself. */
void __purge_module(struct module *mod) {
        free_module(mod);
        do_exit(0);

        /* We should never be here. */
        BUG();
}
EXPORT_SYMBOL(__purge_module);

__purge_module(THIS_MODULE) 调用它会卸载你的模块并且不会导致页面错误(因为你不会返回到模块的代码)。但是,我仍然不建议这样做。我已经完成了一些简单的容量测试(我插入了一个使用此函数的模块约 10000 次,以查看是否存在任何资源泄漏——据我所知,没有任何资源泄漏)。

关于linux - 内核模块如何卸载自身而不在内核日志中产生错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32413204/

相关文章:

c++ - 加载具有相同静态链接函数的两个共享库时使用哪个函数

c - 以下功能的目的是什么?

linux - softirq 和 tasklet 在哪个上下文中?

嵌入式 Linux 从 USB 端口读取和写入视频

c - 如何从 Linux 内核空间模块执行/调用用户空间定义的函数?

linux - 在 LAMP CentOS VPS 上克隆 Git Repo 时出现 500 Internal Server Error

linux - 如何借助shell脚本通过IP知道目标计算机正在使用的操作系统?

c++ - 使用管道从 STDIN 读取 fork 进程时出现问题

c - 何时使用 fcheck() 或 fcheck_files() 以及为了什么?

linux-kernel - 内核模块分析器