How to call exported kernel module functions from another module?

旧城冷巷雨未停 提交于 2019-11-27 04:04:11

From my research, it seems that those are the only three ways to handle this situation, and I've gotten each of them to work, so I think I'll just pick my favorite out of those.

Minimal QEMU + Buildroot example

I have tested the following in a fully reproducible QEMU + Buildroot environment, so maybe having this working version version will help you find out what is wro with your code.

GitHub upstream is centered on the files: dep.c | dep2.c | Makefile

dep.c:

#include <linux/delay.h> /* usleep_range */
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");

int lkmc_dep = 0;
EXPORT_SYMBOL(lkmc_dep);
static struct task_struct *kthread;

static int work_func(void *data)
{
    while (!kthread_should_stop()) {
        printk(KERN_INFO "%d\n", lkmc_dep);
        usleep_range(1000000, 1000001);
    }
    return 0;
}

static int myinit(void)
{
    kthread = kthread_create(work_func, NULL, "mykthread");
    wake_up_process(kthread);
    return 0;
}

static void myexit(void)
{
    kthread_stop(kthread);
}

module_init(myinit)
module_exit(myexit)

dep2.c:

#include <linux/delay.h> /* usleep_range */
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");

extern int lkmc_dep;
static struct task_struct *kthread;

static int work_func(void *data)
{
    while (!kthread_should_stop()) {
        usleep_range(1000000, 1000001);
        lkmc_dep++;
    }
    return 0;
}

static int myinit(void)
{
    kthread = kthread_create(work_func, NULL, "mykthread");
    wake_up_process(kthread);
    return 0;
}

static void myexit(void)
{
    kthread_stop(kthread);
}

module_init(myinit)
module_exit(myexit)

Now you can either do:

insmod dep.ko
insmod dep2.ko

but Buildroot is also already configuring depmod /lib/module/*/depmod with the dependency, so just this is enough to load both:

modprobe dep

If you use CONFIG_KALLSYMS_ALL=y, then the symbol can be seen with:

grep lkmc_dep /proc/kallsyms

see also: Does kallsyms have all the symbol of kernel functions?

OK: You have one module where the function is and one place what wants to import it right?

You must use "EXPORT_SYMBOL("name of the function") such as foo in the place where the function is. So in the "c" file have the function "foo" defined and put in: EXPORT_SYMBOL(foo)

Make sure you have the prototype for "foo" in a common header file (you can have it in separate places for each module and it will work but you are asking for trouble if the signatures change). So say: void foo(void *arg);

Then the other module that wants it just invoke "foo" and you are good.

Also: Make sure that you load the module with foo first. If you have cross dependencies like module2 needs foo from module1 and module1 needs bar from module2 you need to have one register functions with another. If you want to know please ask a separate Q.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!