我的驅動在I2C初始化之前就運行起來了,而這時I2C提供的API還處於不可用狀態。查了很多資料,網上有人說所有使用module_init這個宏的驅動程序的起動順序都是不確定的(我沒有查到權威的資料)。
所有的__init函數在區段.initcall.init中還保存了一份函數指針,在初始化時內核會通過這些函數指針調用這些__init函數指針,並在整個初始化完成後,釋放整個init區段(包括.init.text,.initcall.init等)。
注意,這些函數在內核初始化過程中的調用順序只和這裡的函數指針的順序有關,和1)中所述的這些函數本身在.init.text區段中的順序無關。在2.4內核中,這些函數指針的順序也是和鏈接的順序有關的,是不確定的。在2.6內核中,initcall.init區段又分成7個子區段,分別是
1
2
3
4
5
6
7
| .initcall1.init .initcall2.init .initcall3.init .initcall4.init .initcall5.init .initcall6.init .initcall7.init |
1
| core_initcall(fn); |
其他的各個區段的定義方法分別是:
1
2
3
4
5
6
7
| core_initcall(fn) --->.initcall1.init postcore_initcall(fn) --->.initcall2.init arch_initcall(fn) --->.initcall3.init subsys_initcall(fn) --->.initcall4.init fs_initcall(fn) --->.initcall5.init device_initcall(fn) --->.initcall6.init late_initcall(fn) --->.initcall7.init |
而與2.4兼容的initcall(fn)則等價於device_initcall(fn)。各個子區段之間的順序是確定的,即先調用.initcall1.init中的函數指針,再調用.initcall2.init中的函數指針,等等。而在每個子區段中的函數指針的順序是和鏈接順序相關的,是不確定的。
在內核中,不同的init函數被放在不同的子區段中,因此也就決定了它們的調用順序。這樣也就解決了一些init函數之間必須保證一定的調用順序的問題。按照include/Linux/init.h文件所寫的,我在驅動裡償試了這樣兩種方式:
1
2
| __define_initcall( "7" , fn); late_initcall(fn); |
1
| #define late_initcall(fn) __define_initcall("7", fn) |