Initialization of the Linux subsystem _subsys_initcall ()

Source: Internet
Author: User

Overview

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.

Statement of section

The section of the attribute attribute in C is the location that can be used to actively customize the code when the target file is linked, as in the wiki, as seen in the Linux kernel.

The following code is from the Linux kernel source include/linux/init.h file. The following variable names, which use the same syntax rules, hold the addresses of each initialization function.

More importantly, the section attribute is also based on a certain rule.

About section See http://lihuize123123.blog.163.com/blog/static/878290522010420111428109/

/* initcalls are now grouped by functionality into separate   * subsections. ordering inside the subsections is determined *  by link order.  * for backwards compatibility, initcall ()   puts the call in  * the device init subsection. * *  The  ' id '  arg to __define_initcall ()  is needed so that  multiple initcalls * can point at the same handler without  causing duplicate-symbol build errors. */#define  __define_initcall (level,fn,id)   static initcall_t __initcall_# #fn # #id  __used __attribute__ (__section__ (". Initcall"   level  ". Init"))  = fn/* * early initcalls run before initializing  smp. * *  only for built-in code, not modules. */#define  early_initcall (FN) __define_ Initcall ("early", fn,early)/* * a  "pure"  initcall has no dependencies  On anything else, and purely * initializes variables that couldn ' t be statically initialized. * * this only exists for  built-in code, not for modules. */#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) #define  __initcall (FN)  device_initcall (FN) #define  __exitcall (FN)  static exitcall_t __exitcall_# #fn  __exit_call = fn#define  console_initcall (FN)  static initcall_t __initcall_# #fn  __used __section (. Con_ Initcall.init)  = fn#define security_initcall (FN)  static initcall_t __initcall_## Fn __used __section (. Security_initcall.init)  = FN

Register

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

#define INITCALLS* (. initcallearly.init) Vmlinux_symbol (__early_initcall_end) =.; * (. Initcall0.init) * (. initcall0s.init) * (. initcall1.init) * (. initcall1s.init) * (. initcall2.init) * (. Initcall2s.init ) * (. initcall3.init) * (. initcall3s.init) * (. initcall4.init) * (. initcall4s.init) * (. initcall5.init) * (. Initcall5s.ini T) * (. initcallrootfs.init) * (. initcall6.init) * (. initcall6s.init) * (. initcall7.init) * (. initcall7s.init)

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, view init.h file discovery

/** * module_init ()  - driver initialization entry point * @x:  function to be run at kernel boot time or module  Insertion *  * module_init ()  will either be called during do _initcalls ()   (If * builtin)  or at module insertion time  (if  A module).   there can only * be one per module. */# Define module_init (x) __initcall (x), #define  __initcall (FN)  device_initcall (FN)/* don ' t  use these in modules, but some people do... */#define  early _initcall (FN) module_init (FN) #define  core_initcall (FN) module_init (FN) #define  postcore_initcall (FN) Module_init (FN) #define  arch_initcall (FN) module_init (FN) #define  subsys_initcall (FN) Module_init (FN) # Define fs_initcall (FN) module_init (FN) #define  device_initcall (FN) module_init (FN) #define  late_initcall (FN) module_init (FN) 

#define __define_initcall (LEVEL,FN) static initcall_t __initcall_# #fn __used __attribute__ ((__section__ (". Initcall") ". Init")) = fn/* userspace initcalls shouldn ' t depend on anything at the kernel, so we'll * make them run first. */#define __initcall (FN) __define_initcall ("1", fn) #define __exitcall (FN) static exitcall_t __exitcall_# #fn __exit_ Call = Fn#define __init_call__used __section (. Initcall.init)

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

called
Static void __init do_initcalls (void) {initcall_t *fn;for  (fn = __early_ initcall_end; fn < __initcall_end; fn++) Do_one_initcall (*FN);/* Make sure  there is no pending stuff from the initcall sequence */ Flush_scheduled_work ();} Int __init_or_module do_one_initcall (INITCALL_T&NBSP;FN) {int count = preempt_count (); int ret;if  (initcall_debug) Ret = do_one_initcall_debug (FN); Elseret = fn (); msgbuf [0] = 0;if  (Ret && ret != -enodev && initcall_ Debug) sprintf (msgbuf,  "error code %d ",  ret);if  (Preempt_count ()  !=  Count)  {strlcat (msgbuf,  "preemption imbalance ",  sizeof (MSGBUF));p Reempt_count ()  = count;} if  (irqs_disabled ())  {strlcat (msgbuf,  "disabled interrupts ",  sizeof(MSGBUF)); Local_irq_enable ();} if  (Msgbuf[0])  {printk ("initcall %pf returned with %s\n",  fn, msgbuf);} Return ret;}



In BUILDING

Initialization of the Linux subsystem _subsys_initcall ()

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.