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中)
- #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中)
- #define?__define_initcall(level,fn,id)?\ ??
- ????????static?initcall_t?__initcall_##fn##id?__used?\??
- ????????__attribute__((__section__(".initcall"?level?".init")))?=?fn??
?
這其中initcall_t是函數指針,原型如下,
- 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)
- #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段的。
- 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中的函數按順序都執行一遍。
- for?(call?=?__early_initcall_end;?call?<?__initcall_end;?call++)??
- ????????do_one_initcall(*call);??
?
*************************** 本文完 *****************************