c - C 中的内核模块 __init 宏

标签 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 宏。正如文档所说:

The __init macro indicates to compiler that that associated function is only used during initialization. Compiler places all code marked with __init into a special memory section that is freed after initialization

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

最佳答案

概括地说:

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

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

对于内核,代码在特权模式下运行,不会像在用户模式下那样“卸载”未使用的页面。如果一个函数被放在内核的常规代码段中,那么只要内核运行,它就会占用物理内存,这可能是相当长的时间。如果一个函数只被调用一次,那就太浪费空间了。

虽然现在可加载的内核模块一般都可以加载和卸载,所以它们的代码可能不会无限期地占用空间,但是对于一个只会被调用一次的函数占用空间还是有些浪费。

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

关于c - C 中的内核模块 __init 宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48558460/

相关文章:

c - SIGIO 只通知线程池中的最后一个线程

c - 从内核空间的 inode 读取原始字节

c++ - 有没有办法将 #define 指令设为 'expand'?

c - 在我退出之前处理 sigaction 时我的打印品没有出现

c - getchar() 的 getc 文件中是否有等效的 fseek 和 ftell?

linux-kernel - 将数据从 Linux 内核缓冲区零拷贝移动到硬盘

Linux:列出所有从磁盘上不再存在的可执行文件运行的正在运行的进程?

macros - 用于填写自定义字段名称、值和 switch 语句的宏 @ :enum abstract?

macros - 宏规则只匹配第一个模式

c - 如何修复 'Segmentation Fault (core dumped)'错误