在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 MPAD210      *  Quickembed Tech Inc.211      *  Sugars Ling 346619201@qq.com212      */213 #if 1214     #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 add222 #else223     #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 #else2396     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 346619201@qq.com */#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的修改方法的,请留言给我,让我学习,谢谢。

有时,明知错了,却欲罢不能,

在linux设备启动时,修改加载设备驱动的顺序

相关文章:

你感兴趣的文章:

标签云: