0

这是简单的模块程序代码。

#include <linux/module.h>   /* Needed by all modules */
#include <linux/kernel.h>   /* Needed for KERN_INFO */
#include <linux/init.h>     /* Needed for the macros */

static int hello3_data __initdata = 3;

static int __init hello_3_init(void)
{
    printk(KERN_INFO "Hello, world %d\n", hello3_data);
    return 0;
}

static void __exit hello_3_exit(void)
{
    printk(KERN_INFO "Goodbye, world %d\n",hello3_data);
}

module_init(hello_3_init);
module_exit(hello_3_exit);

我已经用__initdata宏初始化了一个变量,用__init. 当我insmod插入模块时,我能够看到日志消息(/var/log/messages)。但是,当我这样做时,rmmod它无法删除它,它说Resource busy.

My question is does the `modules_init` function cleans the memory of `hello3_data`??

or it is done by `module_exit`??.  

有人请解释一下。

4

1 回答 1

3

请在声明变量时hello3_data使用__initdata修饰符,该修饰符指定该变量应仅在__init函数中使用。

尝试使用类似选项重新编译您的内核模块,make CONFIG_DEBUG_SECTION_MISMATCH=y您将看到如下警告:

警告:/home/pengyu/temp/yusen/test_mod.o(.exit.text+0x3):从函数 cleanup_module() 到变量 .init.data:hello3_data
的引用中的部分不匹配函数 __exit cleanup_module() 引用了一个变量 __initdata hello3_data。
当 exit 函数中的错误处理使用 init 路径中的功能时,通常会看到这种情况。
修复通常是删除 hello3_data 的 __initdata 注释,因此它可以在 init 部分之外使用。

您可以简单地删除__initdata并重试。

编辑:

在这里,我试图提供进一步的解释。内核模块本身的格式为ELF (Executable and Linkable Format)(带有一些内核模块特定的部分)。部分.init.fini功能由链接器和加载器支持,包括insmod.

在这种情况下,属性的#define __initdata __section(.init.data)工作方式类似于__attribute__((section(".init.data")))明确指定数据/函数应放入哪个部分。

作为内核模块,.init不能保证在模块初始化后保留该部分,并且该部分内的任何内容都不应该在初始化函数之外被引用。请参阅Linux 设备驱动程序第三版的第 31 页:

定义中的_init 标记可能看起来有点奇怪;这是对内核的一个提示,即给定函数仅在初始化时使用。模块加载器在加载模块后丢弃初始化函数,使其内存可用于其他用途。仅在初始化期间使用的数据有一个类似的标记 ( _initdata)。__init 和 __initdata 的使用是可选的,但值得一试。请确保不要将它们用于初始化完成后将使用的任何函数(或数据结构)

于 2013-11-13T09:35:59.603 回答