在x86系统上,我有一个Linux内核模块(“watcher模块”),每次加载特定内核模块(“目标”)时,内核都会通知内核模块。几乎任何内核模块都可以成为目标。我在an instrumentation system我正在使用它。
当观察者模块处理这样的通知时,如果观察者知道所加载的目标模块的ELF部分的地址,则由于某种原因可能是方便的。有关如何在内核空间中获取此信息的任何想法?
当然,我可以在加载目标后立即在用户空间的/sys/module/<target_name>/sections/
中获取相应文件的内容,然后以某种方式将此数据传递给观察者模块,但这太笨拙了。我想找到一种直接在内核空间中获取此信息的方法。
据我所知,在模块加载器的源代码中,它不会在struct module
中存储节地址,只是为节创建sysfs文件。也许有可能以某种方式找到与这些文件对应的内核对象并从这些对象中读取所需的数据?或者可能使用其他方法?
答案 0 :(得分:5)
在深入了解有关模块各部分的信息如何进入sysfs之后,我发现如果不使用内核内部的结构定义就无法检索它。在我的项目中使用这些东西不是一个选项,所以我最终实现了另一种方法,希望它更可靠。
简而言之,这个想法如下。我的内核模块使用用户模式帮助程序API来启动用户空间进程(实际上是执行我的脚本的shell)。该进程将“目标”内核模块的名称作为参数获取,并从sysfs(/sys/module/<target_name>/sections/
)收集有关其部分的信息。从用户空间,可以容易地获得该信息。之后,它通过debugfs中的文件将收集的数据作为字符串传递给我的内核模块。模块解析字符串并验证其内容。如果一切正常,ELF部分的名称和起始地址将可用。
我承认,使用用户模式助手的技巧非常笨拙,但它可以完成工作。
我已经准备了上述方法的示例实现 - 请参阅"Sections" example。
有关用户模式帮助程序API的详细信息,请参阅内核源代码中的<linux/kmod.c>
和<linux/kmod.h>
中的代码,即call_usermodehelper()
的定义。 this article中提供了示例以及API典型用法的说明。
请注意that article中的示例有点不准确:模块的init函数返回call_usermodehelper()
的结果。但是,后者返回2字节的状态代码(至少在使用UMH_WAIT_PROC
调用时)而不是0或预期init函数返回的负错误代码。这可能会导致运行时警告。 call_usermodehelper()
实际返回的内容解释为here。
答案 1 :(得分:1)
文件linux / kernel / module.c有一些非静态函数(但前面没有这个EXPORT_SYMBOL),比如module_address_lookup(),但是这些函数使用preempt_disable()和_enable()之类的东西。我宁愿不使用这个函数,而是建议使用sysfs-interface,尽管你的驱动程序已经处于内核模式。