Initialization of the Linux subsystem _subsys_initcall (): Those entry functions "go"

Source: Internet
Author: User

after the parsing of the kernel options is complete, the initialization of each subsystem enters the second part-the invocation of the entry function. Usually, USB, PCI subsystem will have a portal named Subsys_initcall, if you choose them as a starting point for the study of the kernel, then please find it first.

Zhu Deyong in the "about work this matter," said, spend half a day to find the entrance, spend the rest of the life to find the exit. See the search for the entrance for our life, for the core code this thing is extremely important.

But many times, the entrance is not only subsys_initcall one, such as PCI.

The following code is from the Linux kernel source include/linux/init.h file

  1. 117 #define Pure_initcall (FN) __define_initcall ("0", fn,1)
  2. 118
  3. 119 #define Core_initcall (FN) __define_initcall ("1", fn,1)
  4. #define CORE_INITCALL_SYNC (FN) __define_initcall ("1s", fn,1s)
  5. 121 #define Postcore_initcall (FN) __define_initcall ("2", fn,2)
  6. 122 #define POSTCORE_INITCALL_SYNC (FN) __define_initcall ("2s", fn,2s)
  7. 123 #define Arch_initcall (FN) __define_initcall ("3", fn,3)
  8. 124 #define ARCH_INITCALL_SYNC (FN) __define_initcall ("3s", fn,3s)
  9. #define Subsys_initcall (FN) __define_initcall ("4", fn,4)
  10. 126 #define SUBSYS_INITCALL_SYNC (FN) __define_initcall ("4s", fn,4s)
  11. 127 #define Fs_initcall (FN) __define_initcall ("5", fn,5)
  12. #define FS_INITCALL_SYNC (FN) __define_initcall ("5s", fn,5s)
  13. 129 #define Rootfs_initcall (FN) __define_initcall ("Rootfs", Fn,rootfs)
  14. #define Device_initcall (FN) __define_initcall ("6", fn,6)
  15. 131 #define DEVICE_INITCALL_SYNC (FN) __define_initcall ("6s", fn,6s)
  16. #define Late_initcall (FN) __define_initcall ("7", fn,7)
  17. 133 #define LATE_INITCALL_SYNC (FN) __define_initcall ("7s", fn,7s)
  18. 134
  19. 135 #define __initcall (FN) Device_initcall (FN)

These portals have a common feature, which is defined using the __define_initcall macro. Their invocation is not random, but in a certain order, this order depends on the __define_initcall macro. The __define_initcall macro is used to place the specified function pointer in the. Initcall.init section.

. Initcall.init Festival

The kernel executable consists of many object files that are linked together. Object files have many sections, such as text, data, init data, bass, and so on. These object files are linked and loaded by a file called a linker script. The function of this linker script is to map the sections of the input object file to the output file, in other words, it links all the input object files to a single executable file, loading the sections of the executable file at the specified address. Vmlinux.lds is a kernel linker script that exists in the arch/<target>/directory, which is responsible for linking sections of the kernel and loading them into memory at a specific offset. Find the Initcall.init in the Vmlinux.lds file to see the following content

    1. __inicall_start =.;
    2. . Initcall.init:AT (ADDR (. initcall.init) –0xc0000000) {
    3. * (. Initcall1.init)
    4. * (. Initcall2.init)
    5. * (. Initcall3.init)
    6. * (. Initcall4.init)
    7. * (. Initcall5.init)
    8. * (. Initcall6.init)
    9. * (. Initcall7.init)
    10. }
    11. __initcall_end =.;

That tells us. The Initcall.init section is divided into 7 sub-sections, and the Xxx_initcall entry function pointer is specifically placed in which sub-section is defined by the Xxx_initcall, __define_initcall macro parameters, For example, Core_initcall puts the function pointer in the. Initcall1.init subsection, Device_initcall places the function pointer in the. Initcall6.init subsection, and so on. The order of the individual sub-sections is determined, that is, the function pointer in the. Initcall1.init is called before calling. Function pointers in Initcall2.init, and so on. The different entry functions are placed in different sub-sections, and therefore the order in which they are called is determined.

Note: The common module_init (x) function in the device driver, viewing the init.h file discovery,

#define MODULE_INIT (x) __initcall (x);

#define __initcall (FN) Device_initcall (FN)

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

This infers that the Module_init call priority is 6 lower than the Subsys_initcall call Priority 4.

Do_initcalls () function

The invocation of those entry functions is done by the Do_initcalls function.

The Do_initcall function passes the for loop, starting with __initcall_start until the end of the __initcall_end, calling the recognized initialization function in turn. The area between __initcall_start and __initcall_end is composed of the. Initcall.init section, which holds the function address of a macro tag in the form of Xxx_initcall, Do_ The Initcall function makes it easy to get a function address and execute the function it points to.

The function address saved by the. Initcall.init section has a certain precedence, and the higher the previous function priority, the higher it is called than the function at the back.

Functions that are called by the Do_initcalls function should not change their priority state and prohibit interrupts. Therefore, after each function is executed, do_initcalls checks whether the function has made any changes and, if necessary, corrects the priority and interrupt state.

In addition, these executed functions can accomplish some tasks that need to be performed asynchronously, and the Flush_scheduled_work function is used to ensure that the Do_initcalls function waits for the end of these asynchronous tasks before returning.

  1. 666 static void __init do_initcalls (void)
  2. 667 {
  3. 668 initcall_t *call;
  4. 669 int count = Preempt_count ();
  5. 670
  6. 671 for (call = __initcall_start, call < __initcall_end; call++) {
  7. 672 ktime_t t0, T1, Delta;
  8. 673 char *msg = NULL;
  9. 674 Char msgbuf[40];
  10. 675 int result;
  11. 676
  12. 677 if (initcall_debug) {
  13. 678 PRINTK ("Calling Initcall 0x%p", *call);
  14. 679 Print_fn_descriptor_symbol (":%s ()",
  15. 680 (unsigned long) *call);
  16. 681 PRINTK ("/n");
  17. 682 t0 = Ktime_get ();
  18. 683}
  19. 684
  20. 685 result = (*call) ();
  21. 686
  22. 687 if (initcall_debug) {
  23. 688 T1 = Ktime_get ();
  24. 689 Delta = ktime_sub (t1, t0);
  25. 690
  26. 691 PRINTK ("Initcall 0x%p", *call);
  27. 692 Print_fn_descriptor_symbol (":%s ()",
  28. 693 (unsigned long) *call);
  29. 694 PRINTK ("returned%d./n", result);
  30. 695
  31. 696 PRINTK ("Initcall 0x%p ran for%ld msecs:",
  32. 697 *call, (unsigned long long) delta.tv64 >> 20);
  33. 698 Print_fn_descriptor_symbol ("%s ()/n",
  34. 699 (unsigned long) *call);
  35. 700}
  36. 701
  37. 702 if (Result && result! =-enodev && initcall_debug) {
  38. 703 sprintf (msgbuf, "error code%d", result);
  39. 704 msg = MSGBUF;
  40. 705}
  41. 706 if (Preempt_count ()! = count) {
  42. 707 msg = "preemption imbalance";
  43. 708 Preempt_count () = count;
  44. 709}
  45. 710 if (irqs_disabled ()) {
  46. 711 msg = "disabled interrupts";
  47. 712 local_irq_enable ();
  48. 713}
  49. 714 if (msg) {
  50. 715 PRINTK (kern_warning "Initcall at 0x%p", *call);
  51. 716 Print_fn_descriptor_symbol (":%s ()",
  52. 717 (unsigned long) *call);
  53. 718 PRINTK (": Returned with%s/n", msg);
  54. 719}
  55. 720}
  56. 721
  57. 722/* Make sure there are no pending stuff from the initcall sequence */
  58. 723 Flush_scheduled_work ();
  59. 724}
at present, the startup process of Linux driver is researched, this article explains the order of the Linux subsystem calls in detail, and also explains the sequence of call of the device driver, which is worth collecting.

This article comes from: http://blog.csdn.net/yimiyangguang1314/article/details/7312209

Initialization of the Linux subsystem _subsys_initcall (): Those entry functions "go"

Related Article

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.