根据我在Linux操作系统中读取模块初始化的信息,我发现具有 __ init 等前缀的函数调用将会被放置在一个ELF位置。
例如我们通常写道:
int __init module_start()
{
....
}
那么在初始化结束后可以覆盖或删除特定的ELF位置,如果是这样的话?如果我们想再次使用初始化,或者我想重新初始化任何模块,接下来的方法是什么,知道初始化例程已被删除的事实?
答案 0 :(得分:2)
__init
是一个Linux内核宏,它有点类似于普通的gcc __attribute__(constructor)
,还有一个额外的功能,它也被解释为提示代码可以被释放一次它已经运行(仅模块,依赖于平台)。在"正常" gcc / glibc C程序,libc负责调用任何init(和fini)函数,在内核中你需要明确地使用module_init()
(和module_exit()
)。
来自include/linux/init.h
:
/* These macros are used to mark some functions or
* initialized data (doesn't apply to uninitialized data)
* as `initialization' functions. The kernel can take this
* as hint that the function is used only during the initialization
* phase and free up used memory resources after
[...]
#define __init __section(.init.text) __cold notrace
有类似的宏来标记退出函数和数据。这些是编译器/链接器指令:
__section()
将代码放入.init.text
部分(放弃)__cold
指示编译器(通过__attribute__()
不优化调用路径,因为很少调用该函数(一次!)notrace
以防止ftrace 重新调用模块初始化的一种简单方法是卸载并重新加载模块(有时用于使设备未被修复)。
如果初始化例程的某些部分在运行时可能有用,可以将它们放在而不是标记为__init
的函数中,并从实际初始化中调用
功能。您可以使用__init
标记多个函数,在module_init()
中也必须使用一个函数,否则您的代码不应调用此函数。重点是,模块初始化代码与设置内核API一样重要,因为它是关于初始化任何硬件或非硬件驱动程序功能(我猜测是你遇到的问题)。
另见: