Initialization calls in Linux

来源:互联网 发布:网络通信sig加密 编辑:程序博客网 时间:2024/05/24 05:08

Thereare many initialization calls in Linux kernel and these initcalls aregrouped by functionality into separate subsections in Linux-2.6.18,such as “core_initcall(ksysfs_init)” and“arch_initcall(au1xxx_platform_init)”.

Both“core_initcall” and “arch_initcall” are macros which are defined inlinux-2.6.18/include/linux/init.h. The following shows the definitionwhen these are built in kernel (not in module):

#define __define_initcall(level,fn) /

       static initcall_t __initcall_##fn __attribute_used__ /

       __attribute__((__section__(".initcall" level ".init"))) = fn

 

#define core_initcall(fn)        __define_initcall("1",fn)

#define postcore_initcall(fn)         __define_initcall("2",fn)

#define arch_initcall(fn)        __define_initcall("3",fn)

#define subsys_initcall(fn)            __define_initcall("4",fn)

#define fs_initcall(fn)                  __define_initcall("5",fn)

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

#define late_initcall(fn)         __define_initcall("7",fn)

 

#define __initcall(fn) device_initcall(fn)

From these, we can find that all initcalls declared with these initcall macros will be linked to “.initcall” section.

Inlinux kernel link file for MIPS(linux-2.6.18/arch/mips/kennel/vmlinux.lds.S), we can find “.initcall”section is linked like this:

  __initcall_start = .;

  .initcall.init : {

       *(.initcall1.init)

       *(.initcall2.init)

       *(.initcall3.init)

       *(.initcall4.init)

       *(.initcall5.init)

       *(.initcall6.init)

       *(.initcall7.init)

  }

  __initcall_end = .;

So all initcalls functions is saved in the memory range between __initcall_start and __initcall_end.

Allthese initcalls will be called in do_initcalls() which is implementedin linux-2.6.18/init/main.c and it is called by “init” thread whenbooting up Linux kernel. These initcalls are called like this:

static void __init do_initcalls(void)

{

       initcall_t *call;

       int count = preempt_count();

 

       for (call = __initcall_start; call < __initcall_end; call++) {

              char *msg = NULL;

              char msgbuf[40];

              int result;

 

             

 

              result = (*call)();

 

             

              }

       }

 

       /* Make sure there is no pending stuff from the initcall sequence */

       flush_scheduled_work();

}

Fromthe code we can find we get the initcall function pointer with“__initcall_start” and “__initcall_end” which is defined in linux linkfile vmlinux.lds.S.

原创粉丝点击