An article explaining kernel module dependencies!

foreword

I don’t know if you have ever thought that in a kernel module code, printka function will be used, and this function is not implemented by us, it is part of the kernel code, but why can we compile it?

The reason why our code can be compiled is because the compilation of the module is only compiled and not linked .

The compiled .kofile is an ordinary ELFfile . Using filecommands and nmcommands, we can see related information:

# file vser.ko
vser.ko ELF 32-bit LSB relocatable, Intel 80386, vserion 1 (SYSV), BuildID[sha1]=0x09ca747e6f75c65v19a5da9102113v98d7cea24, not stripped
# nm vser.ko
......
00000004 d port
    U printk
00000000 t vser_exit
00000000 t vser_init

vser_initand vser_exitare the entry function and exit function of the module respectively. nmWhen you use the command to view the symbol information of the module object file, you can see that the symbol type of vser_exitand is , indicating that they are functions .vser_initt

And printkthe symbol type is U, which means it is a pending symbol . It means that the address of this symbol is not known during the compilation phase, because it is defined in other files and is not compiled together with the module code.

How to solve the address problem of the printk function? The answer is to use EXPORT_SYMBOLa macro to printkexport it.

EXPORT_SYMBOL export symbols

General principle: Use EXPORT_SYMBOLmacros to generate a specific structure and put it in ELFa specific segment of the file. During the startup process of the kernel, the exact address of the symbol will be filled into a specific member of this structure .

When the module is loaded, the loader will process pending symbols, search for the name of the symbol in the special segment, and if found, fill the obtained address into the corresponding segment of the loaded module, so that the address of the symbol can be determined.

Using this method to process pending symbols is actually equivalent to postponing the linking process and performing dynamic linking, which is similar to the reason why ordinary applications use shared library functions . It can be found that the kernel will have a large number of symbol exports, providing a rich infrastructure for the module.

kernel module dependencies

Normally, a module only uses symbols exported by the kernel and does not export symbols itself. But if a module needs to provide global variables or functions for use by other modules, then these symbols need to be exported.

This is more common when one driver calls another driver's code, so that a dependency relationship is formed between modules, and the module that uses the exported symbol will depend on the module that exported the symbol.

To give a specific example, the following are two C files that vser.ccall dep.cvariables and functions in:

vser.c

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

extern int expval;
extern void expfun(void);

static int __init vser_init(void)
{
 printk("vser_init\");
 printk("expval:%d\n", expval);
 expfun();
 
 return 0;
}

static void __exit vser_exit(void)
{
 printk("vser_exit\n");
}

module_init(vser_init);
module_exit(vser_exit);

dep.c

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

static int expval = 5;
EXPORT_SYMBOL(expval);

static void expfun(void)
{
 printk("expfun");
}EXPORT_SYMBOL_GPL(expfun);

Key points of Makefile:

obj-m := vser.o
obj-m += dep.o

In the above code, dep.c defines a variable expvaland a function , which are used and exported expfunrespectively . And the variables and functions called in it , after compiling and installing:EXPORT_SYMBOLEXPORT_SYMBOL_GPLvser.cdep.c

# modprobe vser
# dmesg
[58278.204677] vser_init
[58278.204683] expval:5
[58287.206464] expfun

As can be seen from the output information, the variables and functions vser.care correctly referenced .dep.c

  Information through train: Linux kernel source code technology learning route + video tutorial kernel source code

Learning through train: Linux kernel source code memory tuning file system process management device driver/network protocol stack

Here are three important notes:

  • If you use insmodthe command to load the module, you must first load the dep module, and then load the vser module .

Because the vser module uses the dep module. It can be seen from this that modprobecommands are superior to insmodcommands in that they can automatically load dependent modules. And this is thanks to depmodthe command, depmodwhich generates the dependency information of the module and saves it in /lib/modules/5.10.111-64-generic/modules.depthe file. Among them, 5.10.111-64-generic is the kernel source version. Viewing this file reveals the modules that the vser module depends on.

# cat /lib/modules/5.10.111-64-generic/modules.dep
......
extra/vser.ko: extra/dep.ko
extra/dep.ko:
  • There is a dependency between the two modules. If you compile the two modules separately, a warning message similar to the following will appear, and even if the loading sequence is correct, the loading will not succeed :
WARNING: "expfun" [/home/ubuntu/driver/module/vser.ko] undefined!
WARNING: "expval" [/home/ubuntu/driver/module/vser.ko] undefined!

# sudo insmod dep.ko
# sudo insmod vser.ko
insmod:error inserting 'vser.ko': -1 Invalid parameters

This is because the entry for and vseris not found in the kernel's symbol table when the module is compiled , and the module is completely unaware of the module's existence.expvalexpfunvserdep

The solution to this problem is to compile the two modules together, or put the dep module in the kernel source code, first compile all the modules under the kernel source code, and then compile the vser module.

  • When uninstalling a module, first uninstall the vser module, and then uninstall the dep module, otherwise the dep module will not be uninstalled because it is used by the vser module .

The kernel will create a link to the module's dependencies, and the module can only be unloaded if the linked list of dependencies on this module is empty.

 

Guess you like

Origin blog.csdn.net/youzhangjing_/article/details/130223514