使用宏* __ init *作为前缀的函数会发生什么?

时间:2015-01-16 08:38:12

标签: kernel init elf

根据我在Linux操作系统中读取模块初始化的信息,我发现具有 __ init 等前缀的函数调用将会被放置在一个ELF位置。

例如我们通常写道:

int __init module_start()
{
....
}

那么在初始化结束后可以覆盖或删除特定的ELF位置,如果是这样的话?如果我们想再次使用初始化,或者我想重新初始化任何模块,接下来的方法是什么,知道初始化例程已被删除的事实?

1 个答案:

答案 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一样重要,因为它是关于初始化任何硬件或非硬件驱动程序功能(我猜测是你遇到的问题)。

另见: