简体   繁体   中英

Inter-dependent out-of-tree kernel loadable modules in Linux

I have a design for two kernel loadable modules that I am building out of tree. These modules may run independently or they may work together (use the services of each other) when both are loaded.

So I have module1.ko with funcA and funcB. I also have module2.ko with funcC and funcD. When module1.ko is loaded by itself, it simply uses funcA and funcB. But if module2.ko is also loaded, I would like to make it so that module1.ko can use funcC.

How can module1.ko detect if module2.ko is loaded so that it knows if funcC is available for it to use?

Also, since I'm building both of these modules outside of the Linux Kernel, how do I update my Makefile to add this conditional dependency at build time?

My Makefile currently looks something along the lines of this:

MODULE_NAME=module1
SOURCE_FILES=module1_driver.c
CROSS_COMPILER=powerpc-timesys-linux-gnu-
ARCH=powerpc

ifneq ($(KERNELRELEASE),)

    obj-m := $(MODULE_NAME).o
    $(MODULE_NAME)-objs := $(SOURCE_FILES:.c=.o)
    ccflags-y := -I$(src)/../common
    sinclude $(TOPDIR)/Rules.make

else

    KERNELDIR ?= ../../linux/2.6-xlnx-rt
    PWD := $(shell pwd)

default:
    $(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILER) -C $(KERNELDIR) M=$(PWD) modules

clean:
    $(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILER) -C $(KERNELDIR) M=$(PWD) clean
    rm -rf ../common/*.o module1_test

endif

A simple solution is to use a third module.

The third woulf always be loaded, and will contain an exported function pointer.
module2 will set the pointer, module1 will use it if it's set.

As per ugoren's answer, you can just add some hooks into a machine file.

static void (*funcA_ptr)();
void register_funcA(void(*)() fnc)
{
  funcA_ptr = fnc;
}
EXPORT_SYMBOL(register_funcA);
void funcA_proxy()
{
  if(funcA_ptr)
       funcA_ptr();
}
EXPORT_SYMBOL(funcA_proxy);

This overhead is so small, there is no need to make it a module.

Another mechanism is to look through module.h . The functions,

  1. int register_module_notifier(struct notifier_block * nb);
  2. int unregister_module_notifier(struct notifier_block * nb);

Can be used to get notified whenever any module is loaded. The notifier functions are passed enum module_state and a pointer to the module structure. You can use this to walk through the exported symbols and patch the function pointers contained with-in the module.

The first solution seems best for a limited number of functions and the 2 nd seem good if you anticipate that many functions may eventually be added like this. The 2 nd solution supports module removal, but you can also do this with the first by using register_funcA(NULL); in a module_exit() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM