如何在Linux中的初始化调用级别内确定探测顺序

时间:2019-04-24 21:57:30

标签: linux-kernel linux-device-driver embedded-linux

Linux确实根据需要为我们提供了7种不同的初始化级别供您选择。我想知道init级别如何确定要调用哪个模块的init。例如,驱动程序A和驱动程序B都在fs_initcall级别定义了模块初始化。 Linux如何确定首先要呼叫哪一个。

1 个答案:

答案 0 :(得分:0)

对于同一级别,它由Makefile顺序确定,例如,在我的驱动程序/输入/触摸屏/ Makefile中:

obj-$(CONFIG_TOUCHSCREEN_IT7259_I2C)    += it7259_ts_i2c.o
obj-$(CONFIG_TOUCHSCREEN_FTS)           += focaltech_touch/

it7259将首先被调用。

您可以在out / system.map中找到详细顺序:

c116ae80 T __initcall6_start
...
c116b278 t __initcall_it7259_ts_driver_init6
c116b27c t __initcall_fts_ts_init6
...
c116b6a4 T __initcall7_start

如果您更改Makefile中的顺序,请确保清除“ out”文件夹,然后重新生成,然后system.map将以新顺序进行更新。

更多信息:

  1. 以下定义将用于创建.init.data节:

    定义module_init(x)__initcall(x);

    定义__define_initcall(level,fn,id)\

    静态initcall_t initcall _ ## fn ## id __已使用\     __attribute ((( section (“。initcall” level“ .init”))))= fn

每个__initcall(x)将成为.init.data节中的一项,例如:

c116b27c t __initcall_fts_ts_init6
  1. 启动时的初始调用流程: start_kernel-> rest_init-> kernel_init-> do_basic_setup-> do_initcalls

    静态void __init do_initcalls(void) {     诠释级别;

    for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
    do_initcall_level(level);
    

    }

    静态void __init do_initcall_level(int级别) {     extern const struct kernel_param __start ___ param [],__stop ___ param [];     initcall_t * fn;

    strcpy(static_command_line, saved_command_line);
    parse_args(initcall_level_names[level],
            static_command_line, __start___param,
            __stop___param - __start___param,
            level, level,
            repair_env_string);
    
    for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
    do_one_initcall(*fn);
    

    }

    静态initcall_t * initcall_levels [] __initdata = {     __initcall0_start,     __initcall1_start,     __initcall2_start,     __initcall3_start,     __initcall4_start,     __initcall5_start,     __initcall6_start,     __initcall7_start,     __initcall_end, };

在vmlinux.lds中,它将转到.init.data节中的地址。