各个段的优先级由链接脚本定义
#define INITCALLS /
*(.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是在文件arch/xxx/kernel/vmlinux.lds.S定义的:
__initcall_start = .;
INITCALLS
__initcall_end = .;
664static void __init do_initcalls(void)
665{
666 initcall_t *call;
667 int count = preempt_count();
668
669 for (call = __initcall_start; call < __initcall_end; call++) {
.。。。。
682
683 result = (*call)();
684
。。。 }
720 /* Make sure there is no pending stuff from the initcall sequence */
721 flush_scheduled_work();
722}
因此__initcall_fnx,数字越小,越先被调用,故arch_initcall优先于module_init所修饰的函数。
arch_initcall修饰的函数的调用顺序如下:
start_kernel 》 rest_init(在setup_arch之后) 》 kernel_init 》 do_basic_setup》do_initcalls(在driver_init()之后),因为platform_bus_init在此之前已经初 始化完毕了,便可将设备挂接到总线上了。
8.4 定义platform_driver
Platform bus和设备都定义好了后,需要定义一个platform driver用来驱动此设备。
对于设备来说:
290struct platform_device s3c_device_i2c = {
291 .name = "s3c2410-i2c",
292 .id = -1,
293 .num_resources = ARRAY_SIZE(s3c_i2c_resource),
294 .resource = s3c_i2c_resource,
295};
296
297EXPORT_SYMBOL(s3c_device_i2c);
根据platform总线上device和driver的匹配规则可知,I2C 的platform driver的名字是s3c2410-i2c。
903/* device driver for platform bus bits */
904
905static struct platform_driver s3c2410_i2c_driver = {
906 .probe = s3c24xx_i2c_probe,
907 .remove = s3c24xx_i2c_remove,
908 .resume = s3c24xx_i2c_resume,
909 .driver = {
910 .owner = THIS_MODULE,
911 .name = "s3c2410-i2c",
912 },
913};
8.5 注册platform_driver