我制作了一个简单的模块,可以在加载时打印 GDT 和 IDT。当它完成工作后,就不再需要它并且可以卸载。但如果它返回负数以停止加载,insmod
会抱怨,并且错误消息将记录在内核日志中。
内核模块如何优雅地卸载自身?
据我所知,使用库存内核是不可能的(您可以按照我在下面描述的方式修改模块加载器核心,但这可能不是一个值得依赖的好东西)。
好的,我看了一下模块加载和卸载代码(kernel/module.c http://lxr.free-electrons.com/source/kernel/module.c)以及一些名字非常可疑的用户module_put_and_exit http://lxr.free-electrons.com/ident?i=module_put_and_exit。似乎没有内核模块可以完成您想做的事情。它们都在模块上下文中启动 kthreads,然后在完成某些操作后终止 kthreads(它们不会自动卸载模块)。
不幸的是,该函数负责卸载大部分模块(free_module http://lxr.free-electrons.com/ident?i=free_module) 是静态定义的kernel/module.c
。据我所知,没有导出函数会调用free_module
从模块内。我觉得这可能是有原因的(尝试从模块内部卸载模块很可能会导致页面错误,因为包含模块代码的页面需要被释放)。虽然这可能可以通过制作来解决noreturn
函数只是schedule
防止当前(无效)任务再次运行(或只是运行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 次,以查看是否存在任何资源泄漏 - 据我所知没有任何资源泄漏)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)