Function call Linux kernel source code analysis of reading a record stored in the different sections of

In the write-driven process, the inlet function and the outlet function we'll use a word to modify them: module_init and module_exit, that after what has been modified, the kernel will be able to call the dog entry function and exit function we write it? Here the kernel call to module_init analysis (here temporarily analysis modules compiled into the kernel, does not involve dynamically loaded modules), to the process as an example to understand the procedure for calling the kernel functions of different segments.

The following functions from the kernel start_kernel start the analysis, the following procedure is invoked:

start_kernel
    rest_init
        kernel_init
            do_basic_setup
                do_initcalls()

Directly see do_initcalls function, see line 6 for the first cycle, it __initcall_start from the beginning to the end __initcall_end, call the function within this range, then these functions where to define it?

 1 static void __init do_initcalls(void)
 2 {
 3     initcall_t *call;
 4     int count = preempt_count();
 5 
 6     for (call = __initcall_start; call < __initcall_end; call++) {/* 调用__initcall_start到__initcall_end内的函数*/
 7         ktime_t t0, t1, delta;
 8         char *msg = NULL;
 9         char msgbuf[40];
10         int result;
11 
12         if (initcall_debug) {
13             printk("Calling initcall 0x%p", *call);
14             print_fn_descriptor_symbol(": %s()",
15                     (unsigned long) *call);
16             printk("\n");
17             t0 = ktime_get();
18         }
19 
20         result = (*call)();
21 
22         if (initcall_debug) {
23             t1 = ktime_get();
24             delta = ktime_sub(t1, t0);
25 
26             printk("initcall 0x%p", *call);
27             print_fn_descriptor_symbol(": %s()",
28                     (unsigned long) *call);
29             printk(" returned %d.\n", result);
30 
31             printk("initcall 0x%p ran for %Ld msecs: ",
32                 *call, (unsigned long long)delta.tv64 >> 20);
33             print_fn_descriptor_symbol("%s()\n",
34                 (unsigned long) *call);
35         }
36 
37         if (result && result != -ENODEV && initcall_debug) {
38             sprintf(msgbuf, "error code %d", result);
39             msg = msgbuf;
40         }
41         if (preempt_count() != count) {
42             msg = "preemption imbalance";
43             preempt_count() = count;
44         }
45         if (irqs_disabled()) {
46             msg = "disabled interrupts";
47             local_irq_enable();
48         }
49         if (msg) {
50             printk(KERN_WARNING "initcall at 0x%p", *call);
51             print_fn_descriptor_symbol(": %s()",
52                     (unsigned long) *call);
53             printk(": returned with %s\n", msg);
54         }
55     }
56 
57     /* Make sure there is no pending stuff from the initcall sequence */
58     flush_scheduled_work();
59 }

Read on, we search the entire kernel source code, you can not find the definition __initcall_start and __initcall_end found, in fact, these two variables are defined in arch / arm / kernel / vmlinux.lds, which is generated in the kernel compile time is the entire source code of the kernel linker script, we have come out of a key part of the code. It can be seen between __initcall_start __initcall_end and is subdivided into a number of sections: the * (. Initcall0.init) ~ * (. Initcall7s.init).

 1  .init : { /* Init code and data        */
 2    *(.init.text)
 3   _einittext = .;
 4   __proc_info_begin = .;
 5    *(.proc.info.init)
 6   __proc_info_end = .;
 7   __arch_info_begin = .;
 8    *(.arch.info.init)
 9   __arch_info_end = .;
10   __tagtable_begin = .;
11    *(.taglist.init)
12   __tagtable_end = .;
13   . = ALIGN(16);
14   __setup_start = .;
15    *(.init.setup)
16   __setup_end = .;
17   __early_begin = .;
18    *(.early_param.init)
19   __early_end = .;
20   __initcall_start = .;
21    *(.initcall0.init) *(.initcall0s.init) *(.initcall1.init) *(.initcall1s.init) *(.initcall2.init) *(.initcall2s.init) *(.initcall3.init) *(.initcall3s.init) *(.initcall4.init) *(.initcall4s.init) *(.initcall5.init) *(.initcall5s.init) *(.initcallrootfs.init) *(.initcall6.init) *(.initcall6s.init) *(.initcall7.init) *(.initcall7s.init)
22   __initcall_end = .;
23   __con_initcall_start = .;
24    *(.con_initcall.init)
25   __con_initcall_end = .;
26   __security_initcall_start = .;
27    *(.security_initcall.init)
28   __security_initcall_end = .;
29 
30   . = ALIGN(32);
31   __initramfs_start = .;
32    usr/built-in.o(.init.ramfs)
33   __initramfs_end = .;
34 
35   . = ALIGN(4096);
36   __per_cpu_start = .;
37    *(.data.percpu)
38   __per_cpu_end = .;
39 
40   __init_begin = _stext;
41   *(.init.data)
42   . = ALIGN(4096);
43   __init_end = .;
44 
45  }

Analysis here, we go back and continue to see the definition of module_init, which is defined in include \ linux \ init.h in:

194 #define module_init(x)    __initcall(x);

135 #define __initcall(fn) device_initcall(fn)

130 #define device_initcall(fn)        __define_initcall("6",fn,6)

107 #define __define_initcall(level,fn,id) \
108      static initcall_t __initcall_##fn##id __attribute_used__ \
109     __attribute__((__section__(".initcall" level ".init"))) = fn
76   typedef int (*initcall_t)(void);

 

According to the above definition, can eventually expand module_init obtained: this means that as long as the call module_init (x), x is defined as initcall_t put the type of function, and this function is a function named __initcall_x6, it is stored in .initcall6. in init, and this section is located between the right and __initcall_start __initcall_end. So it is time to call the kernel function in do_initcalls for loop.

#define module_init(x)     static initcall_t __initcall_x6 __attribute_used__  __attribute__((__section__(".initcall" 6 ".init"))) = x

 

For other segments, it is similar, but calls to the kernel segment defined elsewhere for use in circulation somewhere.

Guess you like

Origin www.cnblogs.com/andyfly/p/11332997.html