How to call exported kernel module functions from another module?

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 wong 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)

And now you can do:

insmod dep.ko
insmod dep2.ko

With that Buildroot setup, things are already configuring depmod /lib/module/*/depmod with the dependency, so just this is enough to load both:

modprobe dep

Also, if you built your kernel with CONFIG_KALLSYMS_ALL=y, then the exported symbol can be seen with:

grep lkmc_dep /proc/kallsyms

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