#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 是:
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
會把 function 放在 .initcall + level 這個section..在 init/main.c : kernel_init 會
do_basic_setup( )
--> do_initcalls()
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();
}
在 vmlinux.lds :
. = ALIGN(16); __setup_start = .; *(.init.setup) __setup_end = .;
__initcall_start = .;
*(.initcallearly.init) __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.init)
*(.initcallrootfs.init)
*(.initcall6.init) *(.initcall6s.init)
*(.initcall7.init) *(.initcall7s.init)
__initcall_end = .;
? 為什摩中間有一個 initcallrootfs ?.. 也就是說各 kernel module 中宣告 xxx_initcall( ) 的 function ,都會以上面 define 的次序,在 start_kernel( ) 時,一一被呼叫..
hibernate.c :
late_initcall(software_resume);
因為在 開完後,手動 resume , sh console 是 OK 的,所以改一下 software_resume( ) 的位置...從 late_initcall( ) 拿出來,在做完
/* Open the /dev/console on the rootfs, this should never fail */
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
printk(KERN_WARNING "Warning: unable to open an initial console.\n");
以後再 call,就 OK 了----> why ?
init/main.c :
start_kernel( )
----> console_init()
----> reset_init( )
-------->kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
------------>sys_open("/dev/console",..)
console_init( ) 跟 上面的 initcall 一樣:
void __init console_init(void)
{
initcall_t *call;
/* Setup the default TTY line discipline. */
tty_ldisc_begin();
/*
* set up the console device so that later boot sequences can
* inform about problems etc..
*/
call = __con_initcall_start;
while (call < __con_initcall_end) {
(*call)();
call++;
printk("*");
}
}
可以打開 System.map 看 symbol:
800301c4 T __con_initcall_start 800301c4 t __initcall_con_init 800301c4 T __initcall_end 800301c8 t __initcall_mxcuart_console_init 800301cc T __con_initcall_end其中 __initcall_con_init 和 __initcall_end 是同一個位置,所以實際上只有兩個 function
boot log 會有兩個 *.
沒有留言:
張貼留言