内核模块如何卸载自身而不在内核日志中生成错误? [英] How can a kernel module unload itself without generating errors in kernel log?

查看:121
本文介绍了内核模块如何卸载自身而不在内核日志中生成错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've made a simple module which prints GDT and IDT on loading. After it's done its work, it's no longer needed and can be unloaded. But if it returns a negative number in order to stop loading, insmod will complain, and an error message will be logged in kernel log.

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

How can a kernel module gracefully unload itself?

推荐答案

据我所知,使用普通内核是不可能的(您可以按照下面所述修改模块加载器内核,但这可能不是一个好方法.依靠的东西.)

As far as I can tell, it is not possible with a stock kernel (you can modify the module loader core as I describe below but that's probably not a good thing to rely on).

好的,所以我看了一下模块的加载和卸载代码( kernel/module.c )以及非常可疑的 module_put_and_exit .似乎没有内核模块可以完成您想做的事情.它们全部在模块上下文中启动kthread,然后在完成某些操作后杀死kthread(它们不会自动卸载模块).

Okay, so I've taken a look at the module loading and unloading code (kernel/module.c) as well as several users of the very-suspiciously named module_put_and_exit. It seems as though there is no kernel module which does what you'd like to do. All of them start up kthreads inside the module's context and then kill the kthread upon completion of something (they don't automatically unload the module).

不幸的是,该函数完成了大部分模块的卸载工作( free_module )在kernel/module.c中静态定义.据我所知,没有导出函数可以从模块内部调用free_module.我觉得这可能是有某些原因的(尝试从自身内部卸载模块很可能会导致页面错误,因为包含该模块代码的页面需要被释放).尽管可以通过创建noreturn函数来解决此问题,该函数在阻止当前(无效)任务再次运行(或仅运行do_exit)之后仅schedule s.

Unfortunately, the function which does the bulk of the module unloading (free_module) is statically defined within kernel/module.c. As far as I can see, there's no exported function which will call free_module from within a module. I feel like there's probably some reason for this (it's very possible that attempting to unload a module from within itself will cause a page fault because the page which contains the module's code needs to be freed). Although this probably could be solved by making a noreturn function which just schedules after preventing the current (invalid) task from being run again (or just running do_exit).

还有一个要问的问题:您确定要执行此操作吗?您为什么不制作一个Shell脚本来加载和卸载模块并每天调用它呢?按我的喜好,自动卸载模块可能离天网太近了.

A further point to ask is: are you sure that you want to do this? Why don't you just make a shell script to load and unload the module and call it a day? Auto-unloading modules are probably a bit too close to Skynet for my liking.

我已经对此进行了一些尝试,并且找到了一种方法,如果您可以修改模块加载器核心,可以找到一种方法.将此功能添加到kernel/module.c,并对include/linux/module.h进行必要的修改:

I've played around with this a bit and have figured out a way to do this if you're okay with modifying the module loader core. Add this function to kernel/module.c, and make the necessary modifications to 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次,以查看是否存在任何资源泄漏-据我所知没有泄漏).

Calling this with __purge_module(THIS_MODULE) will unload your module and won't cause a page fault (because you don't return to the module's code). However, I would still not recommend doing this. I've done some simple volume testing (I inserted a module using this function ~10000 times to see if there were any resource leaks -- as far as I can see there aren't any).

这篇关于内核模块如何卸载自身而不在内核日志中生成错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆