LINUX內核中的xx_initcall初始化標號
?
田海立@CSDN 2011-07-02
?
????????? LINUX內核中有很多的初始化指示標志postcore_initcall(), arch_initcall(), subsys_initcall(), device_initcall(), etc. 這些起什么作用呢?查閱源代碼(android goldfish-2.6.29)并搜索網上相關文章,對此做一總結。
初始化標號
先看這些宏的定義(定義在文件include/linux/init.h中)
view plaincopy to clipboardprint?
#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 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_initcall(),再看看它的定義(同樣定義在文件include/linux/init.h中)
view plaincopy to clipboardprint?
#define?__define_initcall(level,fn,id)?\ ?? ????????static?initcall_t?__initcall_##fn##id?__used?\?? ????????__attribute__((__section__(".initcall"?level?".init")))?=?fn??
#define __define_initcall(level,fn,id) \static initcall_t __initcall_##fn##id __used \__attribute__((__section__(".initcall" level ".init"))) = fn
?
這其中initcall_t是函數指針,原型如下,
view plaincopy to clipboardprint?
typedef?int?(*initcall_t)(void);??
typedef int (*initcall_t)(void);
?
而屬性 __attribute__((__section__())) 則表示把對象放在一個這個由括號中的名稱所指代的section中。
所以__define_initcall的含義是:
1) 聲明一個名稱為__initcall_##fn的函數指針;
2) 將這個函數指針初始化為fn;
3) 編譯的時候需要把這個函數指針變量放置到名稱為 ".initcall" level ".init"的section中。
3. ?放置.initcall.init SECTION
明確了__define_initcall的含義,就知道了是分別將這些初始化標號修飾的函數指針放到各自的section中的。
SECTION“.initcall”level”.init”被放入INITCALLS(include/asm-generic/vmlinux.lds.h)
view plaincopy to clipboardprint?
#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.init)?????????????????????????????????????\?? ????????????*(.initcallrootfs.init)?????????????????????????????????\?? ????????????*(.initcall6.init)??????????????????????????????????????\?? ????????????*(.initcall6s.init)?????????????????????????????????????\?? ????????????*(.initcall7.init)??????????????????????????????????????\?? ????????????*(.initcall7s.init)??
#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.init) \*(.initcallrootfs.init) \*(.initcall6.init) \*(.initcall6s.init) \*(.initcall7.init) \*(.initcall7s.init)
?
__initcall_start和__initcall_end以及INITCALLS中定義的SECTION都是在arch/xxx/kernel/vmlinux.lds.S中放在.init段的。
view plaincopy to clipboardprint?
SECTIONS?? {?? ????????.init?:?{?? ????????????????__initcall_start?=?.;?? ????????????????????????INITCALLS?? ????????????????__initcall_end?=?.;?? ????????}?? }??
SECTIONS
{.init : {__initcall_start = .;INITCALLS__initcall_end = .;}
}
?
4.?? 初始化.initcallxx.init里的函數
而這些SECTION里的函數在初始化時被順序執行(init內核線程->do_basic_setup()[main.c#778]->do_initcalls())。
程序(init/main.c文件do_initcalls()函數)如下,do_initcalls()把.initcallXX.init中的函數按順序都執行一遍。
view plaincopy to clipboardprint?
for?(call?=?__early_initcall_end;?call?<?__initcall_end;?call++)?? ????????do_one_initcall(*call);??
for (call = __early_initcall_end; call < __initcall_end; call++)do_one_initcall(*call);
?
*************************** 本文完 *****************************
總結
以上是生活随笔為你收集整理的LINUX内核中的xx_initcall初始化标号的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。