Как определить порядок проверки в пределах уровня вызова инициализации в Linux - PullRequest
0 голосов
/ 25 апреля 2019

Linux предоставляет нам 7 различных уровней инициализации на выбор в зависимости от наших потребностей.Мне было интересно на уровне инициализации Как он определяет, какой модуль init должен быть вызван.Например, драйвер A и драйвер B имеют модуль init, определенный на уровне @ fs_initcall.Как Linux определяет, какой из них вызывать первым.

1 Ответ

0 голосов
/ 05 мая 2019

Для того же уровня это определяется порядком Makefile, например, в моих драйверах / input / touchscreen / 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 будет использовано следующее определение:

    define module_init (x) __initcall (x);

    определить __define_initcall (уровень, fn, id) \

    статический initcall_t initcall _ ## fn ## id __used \ __atribute (( section (". Initcall" level ".init"))) = fn

каждый __initcall (x) станет элементом в разделе .init.data, например:

c116b27c t __initcall_fts_ts_init6

поток инициализации при загрузке: start_kernel -> rest_init -> kernel_init -> do_basic_setup -> do_initcalls

static void __init do_initcalls (void) {int level;

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

}

static void __init do_initcall_level (int level) {extern const struct kernel_param __start ___ param [], __stop ___ param [];initcall_t * п;

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);
* * +1042} * 1 043 * *

статическая 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.

...