Loading and releasing of Module_init

Source: Internet
Author: User
As you write the C program needs to include the C library header file, Linux kernel programming also need to include kernel header files, most Linux drivers need to include the following three header files:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
The init.h defines the drive initialization and exit-related functions, kernel.h defines commonly used function prototypes and macro definitions, module.h defines the functions, variables, and macros associated with kernel modules.
Almost every Linux driver has a module_init (with the definition of module_exit in Init.h (\include\linux)). Yes, the driver's load depends on it. Why you need such a macro. The reason is that in general
Programming idea, the initialization function of each part will be called in a fixed function such as:

void init (void)

{

Init_a ();
Init_b ();

}

If you add an initialization function, then add one line after Init_b (): Init_c (); This really can complete our function, but there is a certain problem, that is, can not be independent of the addition of initialization functions, each Tim
Add a new function to modify the init function. You can deal with this problem in another way, just use a macro to modify:

void Init_a (void)
{

}

__initlist (init_a, 1);

How does it implement a list of initialization functions through this macro? First look at the definition of __initlist:

#define __init __attribute__ (Unused, __section__ (". Initlist"))

#define __INITLIST (FN, LVL) \
Static initlist_t __init_# #fn __init = {\
Magic:init_magic, \
CALLBACK:FN, \
LEVEL:LVL}

Please note: __section__ (". Initlist"), what does this attribute do? It tells the connector that this variable is stored in the. Initlist section, and if all the initialization functions are using this macro, then each function will have
A corresponding initlist_t struct variable is stored in the. initlist section, which means that we can find pointers to all the initialization functions in the. initlist section. How to find the address of the Initlist section.

extern u32 __initlist_start;
extern u32 __initlist_end;

These two variables work, __initlist_start is the beginning of the. Initlist section, the __initlist_end is the end, and through these two variables we can access all the initialization functions. Where are the two variables defined? In a linker script file

. = ALIGN (4);
. initlist: {
__initlist_start =.;
* (. initlist)
__initlist_end =.;

}

The values of these two variables are exactly defined at the start and end addresses of the. Initlist section, so we can access all the initialization functions through these two variables. Done for us. Let's analyze the Module_init first. The definition is as follows:

#define MODULE_INIT (x) __initcall (x); Include\linux\init.h

#define __initcall (FN) Device_initcall (FN)

#define Device_initcall (FN) __define_initcall ("6", fn,6)

#define __define_initcall (Level,fn,id) \

Static initcall_t __initcall_# #fn # #id __used \

__ATTRIBUTE__ ((__section__ (". Initcall" Level ". Init")) = fn

If a driver wants to use Func as the driving entry, it can be declared as follows: Module_init (func), after being processed by the above macro, becomes __initcall_func6 __used add to the ". Initcall" area of the kernel image.
。 When the kernel is loaded, all entries in ". initcall" are searched and loaded by priority, and the normal driver has a priority of 6. Other module priorities are listed below: the smaller the value, the more it loads first.

#define Pure_initcall (FN) __define_initcall ("0", fn,0)

#define Core_initcall (FN) __define_initcall ("1", fn,1)

#define CORE_INITCALL_SYNC (FN) __define_initcall ("1s", fn,1s)

#define Postcore_initcall (FN) __define_initcall ("2", fn,2)

#define POSTCORE_INITCALL_SYNC (FN) __define_initcall ("2s", fn,2s)

#define Arch_initcall (FN) __define_initcall ("3", fn,3)

#define ARCH_INITCALL_SYNC (FN) __define_initcall ("3s", fn,3s)

#define Subsys_initcall (FN) __define_initcall ("4", fn,4)

#define SUBSYS_INITCALL_SYNC (FN) __define_initcall ("4s", fn,4s)

#define Fs_initcall (FN) __define_initcall ("5", fn,5)

#define FS_INITCALL_SYNC (FN) __define_initcall ("5s", fn,5s)

#define Rootfs_initcall (FN) __define_initcall ("Rootfs", Fn,rootfs)

#define Device_initcall (FN) __define_initcall ("6", fn,6)

#define DEVICE_INITCALL_SYNC (FN) __define_initcall ("6s", fn,6s)

#define Late_initcall (FN) __define_initcall ("7", fn,7)

#define LATE_INITCALL_SYNC (FN) __define_initcall ("7s", fn,7s)

As you can see, the first load declared as Pure_initcall.

In addition to initializing the load, Module_init also has the function of releasing memory later. A large part of the Linux kernel is device-driven code that has initialization and inverse initialization functions, which is what Linux does, adding __init attributes to functions that only need to be initialized to run once, __init Macros tell the compiler that if the module is compiled into the kernel, the function is placed in the (. init.text) segment and the Module_exit parameter is unloaded like __init, and if the drive is compiled into the kernel, the __EXIT macro ignores the cleanup function. Because the modules that are compiled into the kernel do not need to be cleaned up, it is clear that __init and __exit are not valid for dynamically loaded modules and only support full compilation into the kernel.


Releases the memory space occupied by all of these function codes later in the kernel initialization. Connectors place functions with __init attributes in the same section, releasing the entire section after use. When the function is initialized
This area can be cleaned out to conserve system memory when it is finished. The message that Kenrel sees at startup "freeing unused kernel memory:xxxk freed" is associated with it.
We look at the source code, INIT/MAIN.C Start_kernel is the first C function to enter kernel (), in the last line of this function is Rest_init ();

static void Rest_init (void)

{

.....

Kernel_thread (Kernel_init, NULL, CLONE_FS | Clone_sighand);
Unlock_kernel ();
Cpu_idle ();

.....

}

A kernel thread was created with a function at the end of the main function Kernel_init: Init_post ();

The first sentence in this init_post is Free_initmem (), which is used to release initialization code and data.

void Free_initmem (void)

{

if (!machine_is_integrator () &&!machine_is_cintegrator ()) {
Free_area (unsigned long) (&__init_begin),
(unsigned long) (&__init_end),
"Init"); }

}

The next step is to kernel memory management.

Original: http://wenku.baidu.com/view/c9a1b2e9172ded630b1cb66d.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.