在Linux内核模块中,module_init和init_module有什么区别?

12

我一直在尝试移植一些Linux驱动程序,意识到Linux的内核版本2.4和2.6之间存在重大差异。

在内核版本2.4中,模块编程如下所示 -

#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void)      
{ 
printk(KERN_INFO "Hi \n"); 
return 0; 
}

void cleanup_module(void)  
{ 
printk(KERN_INFO "Bye \n"); 
}

但是,对于内核版本2.6,必须执行以下操作才能使用模块 -

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

static int hi_init(void)
{
    printk(KERN_ALERT "Hi \n");
    return 0;
}

static void hi_exit(void)
{
    printk(KERN_ALERT "Bye \n");
}

module_init(hi_init);
module_exit(hi_exit);

Kernel 2.6中这些变化的好处是什么,为什么在Linux的内核2.6中需要这种变化?


2.4 声明意味着您永远无法将模块构建到系统中(因为声明不是静态的)。 - stsquad
1
这里有一个非常好的module_init解释:https://dev59.com/vGMl5IYBdhLWcg3wMkgo - user2311046
3个回答

8

如果你看一下新功能的定义:

/* Each module must use one module_init(). */
#define module_init(initfn)                 \
static inline initcall_t __inittest(void)       \
{ return initfn; }                  \
int init_module(void) __attribute__((alias(#initfn)));

/* This is only required if you want to be unloadable. */
#define module_exit(exitfn)                 \
static inline exitcall_t __exittest(void)       \
{ return exitfn; }                  \
void cleanup_module(void) __attribute__((alias(#exitfn)));

你会发现它确保正确的样板文件被包含,这样这些特殊函数才能被编译器正确处理。这就是Linux的内部API所做的事情,如果有更好的解决问题的方法,它就会不断进化。

是的,但这样做有什么好处呢?指令只是将用户提供的函数名称作为init_module()函数的别名。 - Chethan
可读性、API的一致性和规范的执行是编程中非常重要的。通常情况下,你需要让API符合规范的部分难以出错,这样开发者就可以集中精力解决实际问题。 - stsquad

5
在Kernel 2.6中,[module_init]有什么优势?
需要注意的是,module_init在2.4中也存在。
它为初始化模块和在将模块文件编译到内核中时运行入口函数添加了必要的样板代码,而不是作为一个模块。

1
一个优点是可读性。cdrom_init() 立即告诉您它是 cdrom 驱动程序的 init() 调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接