core_initcall如何調用

一、core_initcall如何調用
1、
在2.6內核中,initcall.init區段又分成7個子區段,分別是
.initcall1.init
.initcall2.init
.initcall3.init
.initcall4.init
.initcall5.init
.initcall6.init
.initcall7.init
當需要把函數fn放到.initcall1.init區段時,只要聲明
core_initcall(fn); 


1.1 core_initcall如何放入init子段的?
舉例:core_initcall(netlink_proto_init);
(1)
 
(2)將fn放入init函數中
 
(2.1)
 
作用:定義函數指針
(2.2)
 


2、其中initcall函數是如何開始運行的?

2.1
先看一下arch/arm/kernel/vmlinux.lds這個文件,其中有如下行:
  __setup_start = .;
   *(.init.setup)
  __setup_end = .;
  __early_begin = .;
   *(.early_param.init)
  __early_end = .;
  __initcall_start = .;
   *(.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 = .;
可以看出,所有屬於.initcall0.init、.initcall0s.init......等輸入段的代碼或數據都會按以上列表的順序放在__initcall_start和__initcall_end這兩個標號之間
 
 
2.1.1 其中vmlinux.lds是怎麼生成的?
內核編譯鏈接過程是依靠vmlinux.lds文件,以arm爲例vmlinux.lds文件位於kernel/arch/arm/vmlinux.lds,但是該文件是由vmlinux-armv.lds.in生成的,根據編譯選項的不同源文件還可以是vmlinux-armo.lds.in,vmlinux-armv-xip.lds.in。
vmlinux-armv.lds的生成過程在kernel/arch/arm/Makefile中

2.2
函數do_initcalls()對這兩個標號進行了訪問,其源代碼如下:
extern initcall_t __initcall_start[], __initcall_end[];
static void __init do_initcalls(void)
{
initcall_t *call;
for (call = __initcall_start; call < __initcall_end; call++)
 do_one_initcall(*call);
  /* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_work();
}
2.3
如果再仔細分析一下do_initcalls()函數的被調用過程,可以看出:
kernel_init()->do_basic_setup()->do_initcalls()
Kernel_init這個函數是作爲一個內核線程被調用的(該線程最後會啓動第一個用戶進程init)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章