C中的内核模块__init宏

时间:2018-02-01 08:39:25

标签: c linux-kernel macros

我想为Linux创建一个可加载的内核模块。 这是代码

#include <linux/module.h>
#include <linux/init.h>

static int __init mymodule_init(void)
{
 printk ("My module worked!\n");
        return 0;
}

static void __exit mymodule_exit(void)
{
 printk ("Unloading my module.\n");
        return;
}

module_init(mymodule_init);
module_exit(mymodule_exit);

MODULE_LICENSE("GPL");

现在注意__init宏。正如医生所说:

  

__init宏向编译器指示该关联函数   仅在初始化期间使用。编译器将所有代码标记为   将__init放入一个特殊的内存部分,然后释放   初始化

我试图理解为什么初始化方法最终会泄漏内存。是由于堆栈中函数调用的FIFO处理吗?

1 个答案:

答案 0 :(得分:2)

非常广泛地说:

可执行代码(编译的源代码)占用内存。现代CPU将读取指令所在的内存部分,并执行它们。对于大多数用户空间应用程序,进程内存的代码段加载一次,并且在程序执行期间永远不会更改。代码总是在那里,除非程序员玩弄它。

这不是一个问题,因为操作系统将管理进程虚拟内存,冷代码段最终将被卸载到交换文件中。物理记忆永远不会被浪费掉#34;就像在用户空间那样。

对于代码在特权模式下运行的内核,什么都不会卸载&#34;用户模式中发生的未使用页面。如果将函数放入内核常规代码段,则只要内核运行就会占用物理内存,这可能需要相当长的时间。如果一个函数只调用一次,那就太浪费了空间。

现在虽然可加载内核模块一般可以加载和卸载,因此它们的代码可能无法无限占用空间,但是为一个只调用一次的函数占用空间仍然有些浪费。

由于现代CPU将代码视为可执行数据的一种形式,因此可以将该数据放入不会无限期保留的内存段中。加载该函数,然后调用该函数,然后该段可用于其他内容。这就是__init宏指示编译器执行的操作。发出可以在被调用后轻松卸载的代码。