1. 程式人生 > >在linux裝置啟動時,修改載入裝置驅動的順序

在linux裝置啟動時,修改載入裝置驅動的順序

在工作中,遇到一個問題:

某一嵌入式linux裝置帶有USB攝像頭和cmos攝像頭,啟動後,都為/dev/video裝置,其中USB攝像頭為/devvideo0,cmos攝像頭為/dev/video3。但是應用層程式中要求USB攝像頭為video3,cmos攝像頭為video0。所以,現在遇到問題了,當系統啟動時,先載入USB攝像頭的驅動,所以先生成video0,後加載cmos驅動,生成video3。現在我們需要把順序修改下:讓cmos攝像頭驅動先載入,USB攝像頭驅動後加載。

方法:1、將cmos攝像頭驅動放到USB驅動前面。

    2、將USB攝像頭驅動放到cmos後面。

 步驟:

首先,通過萬能百度,搜到http://bbs.chinaunix.net/thread-1950216-1-1.html這裡的文章,對我有很大啟發,並且很有參照意義。

現在,我們知道在核心原始碼目錄中linux-3.0.8/include/linux/init.h,其實linux已經為裝置掛載驅動定義了不同的優先順序:

194 #define pure_initcall(fn)       __define_initcall("0",fn,0)
195 
196 #define core_initcall(fn)       __define_initcall("1",fn,1)
197 #define core_initcall_sync(fn)      __define_initcall("1s",fn,1s)
198 #define postcore_initcall(fn)       __define_initcall("2",fn,2)
199 #define postcore_initcall_sync(fn)  __define_initcall("2s",fn,2s)
200 #define arch_initcall(fn)       __define_initcall("3",fn,3)
201 #define arch_initcall_sync(fn)      __define_initcall("3s",fn,3s)
202 #define subsys_initcall(fn)     __define_initcall("4",fn,4)
203 #define subsys_initcall_sync(fn)    __define_initcall("4s",fn,4s)
204 #define fs_initcall(fn)         __define_initcall("5",fn,5)
205 #define fs_initcall_sync(fn)        __define_initcall("5s",fn,5s)
206 #define rootfs_initcall(fn)     __define_initcall("rootfs",fn,rootfs)
207 #define device_initcall(fn)     __define_initcall("6",fn,6)
208 #define device_initcall_sync(fn)    __define_initcall("6s",fn,6s)
209 #define late_initcall(fn)       __define_initcall("7",fn,7)
210 #define late_initcall_sync(fn)      __define_initcall("7s",fn,7s)

212 #define __initcall(fn) device_initcall(fn)
我們寫驅動用的是module_init(),對應的定義是:

#define module_init(x) __initcall(x)

同時上面也定義了:

#define __initcall(fn)device_initcall(fc)

所以,我們得出module_init(),這樣的載入優先順序是6。

所以,我們要麼把cmos驅動檔案中的module_init()改成更高的優先順序,要麼改低USB攝像頭驅動的優先順序。

但是由於我沒有查到cmos相關的驅動所在核心目錄的位置,所以我採用的是後者。

先在優先順序中新增一個優先順序,post_device_initcall(fn),優先順序為8,本來應該是緊著著device_initcall(fn),但是由於我為了方便,而放在了最後,但是本人仍然強烈建議緊接著放,優先順序僅次於device_initcall(fn)。

194 #define pure_initcall(fn)       __define_initcall("0",fn,0)
195 
196 #define core_initcall(fn)       __define_initcall("1",fn,1)
197 #define core_initcall_sync(fn)      __define_initcall("1s",fn,1s)
198 #define postcore_initcall(fn)       __define_initcall("2",fn,2)
199 #define postcore_initcall_sync(fn)  __define_initcall("2s",fn,2s)
200 #define arch_initcall(fn)       __define_initcall("3",fn,3)
201 #define arch_initcall_sync(fn)      __define_initcall("3s",fn,3s)
202 #define subsys_initcall(fn)     __define_initcall("4",fn,4)
203 #define subsys_initcall_sync(fn)    __define_initcall("4s",fn,4s)
204 #define fs_initcall(fn)         __define_initcall("5",fn,5)
205 #define fs_initcall_sync(fn)        __define_initcall("5s",fn,5s)
206 #define rootfs_initcall(fn)     __define_initcall("rootfs",fn,rootfs)
207 
208     /*
209      *  Changed by ljj to make USB camera starts after than cmos camera on MPAD
210      *  Quickembed Tech Inc.
211      *  Sugars Ling [email protected]
212      */
213 #if 1
214     #define device_initcall(fn)     __define_initcall("6",fn,6)
215     #define device_initcall_sync(fn)    __define_initcall("6s",fn,6s)
216     #define late_initcall(fn)       __define_initcall("7",fn,7)
217     #define late_initcall_sync(fn)      __define_initcall("7s",fn,7s)
218     //add
<strong>219     #define post_device_initcall(fn)    __define_initcall("8",fn,8)
220     #define post_device_initcall_sync(fn)   __define_initcall("8s",fn,8s)</strong>
221     //end add
222 #else
223     #define device_initcall(fn)     __define_initcall("6",fn,6)
224     #define device_initcall_sync(fn)    __define_initcall("6s",fn,6s)
225     #define late_initcall(fn)       __define_initcall("7",fn,7)
226     #define late_initcall_sync(fn)      __define_initcall("7s",fn,7s)
227 
228 #endif
現在我們自定義了一個優先順序為8的呼叫:

#define post_device_initcall(fn) __define_initcall("8",fn,8)

#define post_device_initcall_sync(fn) __define_initcall("8s",fn,8s)

新增好了優先順序至init.h,現在就要到對應的驅動檔案中修改呼叫了:

找到USB攝像頭的驅動在linux-3.0.8/driver/media/video/uvc/uvc_driver.c中,將最後的module_init();修改為

2393 #if 1
<strong>2394     post_device_initcall(uvc_init);</strong>
2395 #else
2396     module_init(uvc_init);
2397 #endif
即使用我們剛剛定義的post_device_initcall();   如果一個裝置的驅動有3個關聯驅動,那麼這些驅動模組都得改為post_device_initcall();

最後就是改連結檔案include/asm-generic/vmlinux.lds.h

	/*

	 *	added by ljj to make USB camera starts after than cmos camera on MPAD

	 *	Quickembed Tech Inc.

	 *	Sugars Ling [email protected]

	 */

#if 1

	#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)						\

<strong>  	*(.initcall8.init)						\

  	*(.initcall8s.init)</strong>

#else

	#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)						



#endif
在連結檔案中新增優先順序:

*(.initcall8.init)\

*(.initcall8s.init)

最後,編譯核心zImage即可。最後測試USB攝像頭啟動晚於cmos,且cmos攝像頭裝置號變為/dev/video0,USB攝像頭裝置號變為/dev/video3。修改啟動載入順序成功。

補一句:有人說不需要這麼麻煩,可以直接改Makefile中的obj += XXX.o這個的順序來修改啟動載入的順序,但是我不太清楚,如果檔案不在同一目錄下如何改,所以就沒有嘗試。

同時,如果有人有更好的方法,或者瞭解Makefile的修改方法的,請留言給我,讓我學習,謝謝。