Home  >  Article  >  Operation and Maintenance  >  What are the benefits of introducing module mechanism in linux?

What are the benefits of introducing module mechanism in linux?

青灯夜游
青灯夜游Original
2023-04-06 15:28:341266browse

The benefits of introducing the module mechanism in Linux: 1. When the application exits, it can ignore the release of resources or other cleanup work, but the exit function of the module must carefully undo everything done by the initialization function; 2 , This mechanism helps shorten the development cycle of the module, that is, registration and uninstallation are very flexible and convenient.

What are the benefits of introducing module mechanism in linux?

#The operating environment of this tutorial: linux7.3 system, Dell G3 computer.

What are the benefits of introducing the module mechanism in Linux?

First, the module pre-registers itself to serve a future request, and then its initialization function ends immediately. In other words, the task of the module initialization function is to prepare in advance for future function calls.

Benefits:

  • 1) When the application exits, it can ignore the release of resources or other cleanup work, but the exit function of the module must carefully uninitialize it. Everything the function does.

  • 2) This mechanism helps shorten the module development cycle. That is: registration and uninstallation are very flexible and convenient.

A brief analysis of the Linux module mechanism

Linux allows users to intervene in the kernel by inserting modules. The module mechanism of Linux has not been clear enough for a long time, so this article briefly analyzes the loading mechanism of the kernel module.

Hello World of module!

We test by creating a simple module. The first is the source file main.c and Makefile.

florian@florian-pc:~/module$ cat main.c

#include<linux/module.h>
#include<linux/init.h>
 
static int __init init(void)
{
    printk("Hi module!\n");
    return 0;
}
 
static void __exit exit(void)
{
    printk("Bye module!\n");
}
 
module_init(init);
module_exit(exit);

where init is the module entry function, in the module It is called and executed when loading. exit is the module export function and is called and executed when the module is unloaded.

florian@florian-pc:~/module$ cat Makefile

obj-m += main.o
#generate the path
CURRENT_PATH:=$(shell pwd)
#the current kernel version number
LINUX_KERNEL:=$(shell uname -r)
#the absolute path
LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)
#complie object
all:
    make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
#clean
clean:
    make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

Among them, obj-m specifies The name of the target file. The file name needs to be the same as the source file name (except for the extension) so that make can automatically deduce it.

Then use the make command to compile the module and get the module file main.ko.

florian@florian-pc:~/module$ make

make -C /usr/src/linux-headers-2.6.35-22-generic M=/home/florian/module modules
make[1]: 正在进入目录 `/usr/src/linux-headers-2.6.35-22-generic&#39;
  Building modules, stage 2.
  MODPOST 1 modules
make[1]:正在离开目录 `/usr/src/linux-headers-2.6.35-22-generic&#39;

Use the insmod and rmmod commands to make the module Load and unload operations, and print kernel logs using dmesg.

florian@florian-pc:~/module$ sudo insmod main.ko;dmesg | tail -1
[31077.810049] Hi module!
florian@florian-pc:~/module$ sudo rmmod main.ko;dmesg | tail -1
[31078.960442] Bye module!

Through the kernel log information, it can be seen that the entry and exit functions of the module are correct Call execution.

Module file

Use the readelf command to check the information of the module file main.ko.

florian@florian-pc:~/module$ readelf -h main.ko

##
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2&#39;s complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          1120 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         19
  Section header string table index: 16
We found main.ko The file type is a relocatable target file, which is no different from the general target file format. We know that the target file cannot be executed directly. It needs to go through the process of address space allocation, symbol resolution and relocation of the linker and be converted into an executable file before it can be executed.

So, after the kernel loads main.ko, does it link it?

Module data structure

First, let’s understand the kernel data structure of the module.

linux3.5.2/kernel/module.h:220

struct module
{
    ……
    /* Startup function. */
    int (*init)(void);
    ……
    /* Destruction function. */
    void (*exit)(void);
    ……
};
The init and exit functions of the module data structure The pointer records the module entry and exit functions we defined.

Module loading

Module loading is completed by the kernel system call init_module.

linux3.5.2/kernel/module.c:3009

/* This is where the real work happens */
SYSCALL_DEFINE3(init_module, void __user *, umod,
       unsigned long, len, const char __user *, uargs)
{
    struct module *mod;
    int ret = 0;
    ……
    /* Do all the hard work */
    mod = load_module(umod, len, uargs);//模块加载
    ……
    /* Start the module */
    if (mod->init != NULL)
       ret = do_one_initcall(mod->init);//模块init函数调用
    ……
    return 0;
}
The system call init_module is called by SYSCALL_DEFINE3(init_module. ..) implementation, which has two key function calls. load_module is used for module loading, and do_one_initcall is used to call back the init function of the module.

The implementation of function load_module is.

linux3.5.2/kernel/module.c:2864

/* Allocate and load the module: note that size of section 0 is always
   zero, and we rely on this for optional sections. */
static struct module *load_module(void __user *umod,
                unsigned long len,
                const char __user *uargs)
{
    struct load_info info = { NULL, };
    struct module *mod;
    long err;
    ……
    /* Copy in the blobs from userspace, check they are vaguely sane. */
    err = copy_and_check(&info, umod, len, uargs);//拷贝到内核
    if (err)
       return ERR_PTR(err);
    /* Figure out module layout, and allocate all the memory. */
    mod = layout_and_allocate(&info);//地址空间分配
    if (IS_ERR(mod)) {
       err = PTR_ERR(mod);
       goto free_copy;
    }
    ……
    /* Fix up syms, so that st_value is a pointer to location. */
    err = simplify_symbols(mod, &info);//符号解析
    if (err < 0)
       goto free_modinfo;
    err = apply_relocations(mod, &info);//重定位
    if (err < 0)
       goto free_modinfo;
    ……
}
There are four key functions in load_module function call. copy_and_check copies the module from user space to kernel space, layout_and_allocate allocates address space for the module, simplify_symbols performs symbol resolution for the module, and apply_relocations performs relocation for the module.

It can be seen that when the module is loaded, the kernel performs a linking process for the module file main.ko!

As for the implementation of the function do_one_initcall, it is relatively simple.

linux3.5.2/kernel/init.c:673

int __init_or_module do_one_initcall(initcall_t fn)
{
    int count = preempt_count();
    int ret;
    if (initcall_debug)
       ret = do_one_initcall_debug(fn);
    else
       ret = fn();//调用init module
    ……
    return ret;
}
That is, the module’s entry function init is called .

Module uninstallation

Module uninstallation is completed by the kernel system call delete_module.

linux3.5.2/kernel/module.c:768

SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
        unsigned int, flags)
{
    struct module *mod;
    char name[MODULE_NAME_LEN];
    int ret, forced = 0;
    ……
    /* Final destruction now no one is using it. */
    if (mod->exit != NULL)
       mod->exit();//调用exit module
    ……
    free_module(mod);//卸载模块
    ……
}

Complete the export function function of the module through the callback exit, and finally call free_module to uninstall the module.

Conclusion

It seems that the kernel module is not mysterious. Traditional user programs need to be compiled into executable programs before they can be executed, while module programs only need to be compiled into object files and then loaded into the kernel. The kernel implements the link to the module and converts it into executable code. At the same time, during the process of kernel loading and unloading, the user-defined module entry function and module exit function will be called back through functions to implement corresponding functions.

Related recommendations: "Linux Video Tutorial"

The above is the detailed content of What are the benefits of introducing module mechanism in linux?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn