__init 在 Linux 内核代码中是什么意思?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8832114/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:02:43  来源:igfitidea点击:

What does __init mean in the Linux kernel code?

clinux

提问by Jeegar Patel

In the Linux kernel source code I found this function:

在 Linux 内核源代码中我发现了这个函数:

static int __init clk_disable_unused(void) 
{
   // some code
}

Here I can not understand what does __initmeans.

在这里我无法理解是什么__init意思。

采纳答案by Sangeeth Saravanaraj

include/linux/init.h

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
 *
 * Usage:
 * For functions:
 * 
 * You should add __init immediately before the function name, like:
 *
 * static void __init initme(int x, int y)
 * {
 *    extern int z; z = x * y;
 * }
 *
 * If the function has a prototype somewhere, you can also add
 * __init between closing brace of the prototype and semicolon:
 *
 * extern int initialize_foobar_device(int, int, int) __init;
 *
 * For initialized data:
 * You should insert __initdata between the variable name and equal
 * sign followed by value, e.g.:
 *
 * static int init_variable __initdata = 0;
 * static const char linux_logo[] __initconst = { 0x32, 0x36, ... };
 *
 * Don't forget to initialize data not at file scope, i.e. within a function,
 * as gcc otherwise puts the data into the bss section and not into the init
 * section.
 * 
 * Also note, that this data cannot be "const".
 */

/* These are for everybody (although not all archs will actually
   discard it in modules) */
#define __init      __section(.init.text) __cold notrace
#define __initdata  __section(.init.data)
#define __initconst __section(.init.rodata)
#define __exitdata  __section(.exit.data)
#define __exit_call __used __section(.exitcall.exit)

回答by sashoalm

These are only macros to locate some parts of the linux code into special areas in the final executing binary. __init, for example (or better the __attribute__ ((__section__ (".init.text")))this macro expands to) instructs the compiler to mark this function in a special way. At the end the linker collects all functions with this mark at the end (or beginning) of the binary file.

这些只是用于将 linux 代码的某些部分定位到最终执行二进制文件中的特殊区域的宏。 __init,例如(或更好的__attribute__ ((__section__ (".init.text")))this 宏扩展到)指示编译器以特殊方式标记此函数。最后,链接器收集二进制文件末尾(或开头)带有此标记的所有函数。

When the kernel starts, this code runs only once (initialization). After it runs, the kernel can free this memory to reuse it and you will see the kernel message:

当内核启动时,这段代码只运行一次(初始化)。运行后,内核可以释放此内存以重新使用它,您将看到内核消息:

Freeing unused kernel memory: 108k freed

释放未使用的内核内存:释放 108k

To use this feature, you need a special linker script file, that tells the linker where to locate all the marked functions.

要使用此功能,您需要一个特殊的链接器脚本文件,它告诉链接器在哪里可以找到所有标记的函数。

回答by elmo

Read comment (and docs at the same time) in linux/init.h.

linux/init.h 中阅读评论(同时阅读文档)。

You should also know that gcc has some extensions made specially for linux kernel code and it looks like this macro uses one of them.

你还应该知道 gcc 有一些专门为 linux 内核代码制作的扩展,看起来这个宏使用了其中之一。

回答by Geoffroy

__init is a macro defined in ./include/linux/init.h which expands to __attribute__ ((__section__(".init.text"))).

__init 是 ./include/linux/init.h 中定义的宏,它扩展为__attribute__ ((__section__(".init.text"))).

It instructs the compiler to mark this function in a special way. At the end the linker collects all functions with this mark at the end (or begin) of the binary file. When the kernel starts, this code runs only once (initialization). After it runs, the kernel can free this memory to reuse it and you will see the kernel

它指示编译器以特殊方式标记此函数。最后,链接器收集二进制文件末尾(或开头)带有此标记的所有函数。当内核启动时,这段代码只运行一次(初始化)。它运行后,内核可以释放这块内存以重用它,您将看到内核

回答by naveen kumar r

This demonstrates a feature of kernel 2.2 and later. Notice the change in the definitions of the initand cleanupfunctions. The __initmacro causes the initfunction to be discarded and its memory freed once the initfunction finishes for built-in drivers, but not loadable modules. If you think about when the initfunction is invoked, this makes perfect sense.

这演示了内核 2.2 及更高版本的功能。注意initcleanup函数定义的变化。该__init宏导致的init被丢弃的功能和它的内存一旦释放init功能完成对内置的驱动程序,但没有可加载模块。如果您考虑init调用函数的时间,这是完全合理的。

source

来源

回答by Nnaik

When you compile and insert a Linux kernel module into the kernel the first function to be executed is __init.This function is basically used to perform initialization before you perform the main operations like registering a device driver etc, There is another function with the opposite effect __exit which is called when you remove the kernel module which is again used to remove some registered device or any such similar function

当你编译并插入一个 Linux 内核模块到内核中时,首先要执行的函数是 __init。这个函数基本上是用来在你执行注册设备驱动程序等主要操作之前进行初始化,还有另一个函数具有相反的效果__exit 删除内核模块时调用,该模块再次用于删除某些已注册的设备或任何此类类似功能