linux-kernel - 可以延迟加载导出的符号吗?

标签 linux-kernel kernel-module kernel

我正在使用一些 linux 内核模块,并且有一个与循环加载问题相关的问题。

模块 A 首先加载并导出许多符号以供模块 B 或 C 使用。然后模块 B 或 C 被加载并且符号存在以供它们使用。

但是,我现在发现模块 A 需要来自模块 B 或 C 的符号,但仅在运行时,不需要初始化模块。因此,当 A 加载时,它当然会发现该符号尚不存在。我什至在模块 A 中将符号标记为外部,但这也不起作用。

是否可以在模块 A 加载后延迟符号的加载,尽管在加载 B 或 C 之前它还不存在?

最佳答案

这种情况通常使用回调来解决。

假设模块 A 导出函数以注册/取消注册回调。 B 和/或 C 使用这些函数并向 A 提供适当的回调。当需要时,A 检查是否设置了回调并调用它们。

像这样的东西(为了简单起见,没有错误处理和锁定):

/* Module A */
struct a_ops /* Better to define struct a_ops in a header file */
{
    void (*needed_func)(void);
    void (*another_needed_func)(void);
}; 
...
struct a_ops ops = {
    .needed_func = NULL;
    .another_needed_func = NULL;
};
...
int a_register_needed_funcs(struct a_ops *a_ops)
{
    ops.needed_func = a_ops->needed_func;
    ops.another_needed_func = a_ops->another_needed_func;
}
EXPORT_SYMBOL(a_register_needed_funcs);

void a_unregister_needed_funcs()
{
    ops.needed_func = NULL;
    ops.another_needed_func = NULL;
}
EXPORT_SYMBOL(a_unregister_needed_funcs);

...
/* Call the specified callbacks when needed: */
void do_something(void)
{
    if (ops.needed_func != NULL) {
        ops.needed_func();
    }
    else {
            /* the callback is not set, handle this: report error, ignore it or
             * do something else */
            ...
    }
}
...

/* Modules B and C */
/* Their code #includes the file where struct a_ops is defined. 
 * The module registers the callbacks, for example, in its init function
 * and unregister in exit function. */
...
static void func(void)
{
    ...
}

static void another_func(void)
{
    ...
}

struct a_ops my_funcs = {
    .needed_func = func;
    .another_needed_func = another_func;
};

int __init my_module_init(void)
{
    ...
    result = a_register_needed_funcs(&my_funcs);
    ... 
}
void __exit my_module_exit(void)
{
    ...
    a_unregister_needed_funcs();
    ...
}

这类似于内核中的文件操作和许多其他回调操作。假设用户想要从自定义驱动程序维护的字符设备中读取数据。内核本身(准确地说是 VFS)接收请求但不能自己处理。它将请求转发给已为该设备注册其文件操作回调的自定义驱动程序。反过来,驱动程序使用内核正确导出的函数,如 cdev_add() , ETC。

关于linux-kernel - 可以延迟加载导出的符号吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17031220/

相关文章:

linux - 安装新内核时如何自动编译linux内核模块?

linux - 如何从 Linux 内核模式设置进程的亲和性?

linux - Netfilter Hook 注册到网络子系统

c - 内核参数更改信号

linux - 术语 "user space"和 "kernel space"是指物理内存吗?

operating-system - 错误系统调用 : Function not implemented

linux - 为什么 fd[1] 是写的而 fd[0] 是读的?

c - 如何使用来自 Linux 内核模块的 Linux 系统调用

linux - LKM - 无法编译模块 - 缺少头文件但安装了头包

linux - 飞溅停止并出现错误 "unregister_netdevice: waiting for lo to become free"