ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2011年9月21日 星期三

initcall, & hibernate, resume, console.

在 include/linux/init.h 有定義: #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 會有兩個 *.

沒有留言:

標籤

網誌存檔