gpt4 book ai didi

linux-kernel - Linux如何确定模块init调用的顺序?

转载 作者:行者123 更新时间:2023-12-03 10:25:24 25 4
gpt4 key购买 nike

我有一个带有 SPI 闪存的设备,我想在该闪存设备上使用 UBIFS 文件系统作为我的 rootfs。我面临的问题是 UBI 模块在 SPI 模块初始化之前初始化。因此,当 UBI 加载时,它无法连接到我告诉它的 UBI 设备(通过内核命令行),因此没有 rootfs。下面的控制台输出说明了这一点。

我已经深入研究了源代码,足以看到 init/main.c有一个 do_initcalls()简单地调用函数指针列表的函数。这些函数指针指向所有 module_init()内核内置模块的功能。这些函数指针被放置在内核二进制文件的一个特殊部分,所以这个顺序是在编译时选择的。但是,我还没有弄清楚这个顺序是如何确定的。

    [    0.482500] UBI error: ubi_init: UBI error: cannot initialize UBI, error -19
[ 0.492500] atmel_spi atmel_spi.0: Using dma0chan0 (tx) and dma0chan1 (rx) for DMA transfers
[ 0.500000] atmel_spi atmel_spi.0: Atmel SPI Controller at 0xf0000000 (irq 13)
[ 0.507500] m25p80 spi0.1: mx25l25635e (32768 Kbytes)
[ 0.512500] Creating 7 MTD partitions on "jedec_flash":
[ 0.520000] 0x000000000000-0x000000020000 : "loader"
[ 0.527500] 0x000000020000-0x000000060000 : "u-boot"
[ 0.537500] 0x000000060000-0x000000080000 : "u-boot-env"
[ 0.547500] 0x000000080000-0x000000280000 : "kernel0"
[ 0.557500] 0x000000280000-0x000000480000 : "kernel1"
[ 0.567500] 0x000000480000-0x000001240000 : "fs"
[ 0.575000] 0x000001240000-0x000002000000 : "play"
[ 0.590000] AT91SAM9 Watchdog enabled (heartbeat=15 sec, nowayout=0)
[ 0.607500] TCP cubic registered
[ 0.615000] VFS: Cannot open root device "ubi0:root0" or unknown-block(0,0)
[ 0.622500] Please append a correct "root=" boot option; here are the available partitions:
[ 0.630000] 1f00 128 mtdblock0 (driver?)
[ 0.635000] 1f01 256 mtdblock1 (driver?)
[ 0.640000] 1f02 128 mtdblock2 (driver?)
[ 0.645000] 1f03 2048 mtdblock3 (driver?)
[ 0.650000] 1f04 2048 mtdblock4 (driver?)
[ 0.655000] 1f05 14080 mtdblock5 (driver?)
[ 0.660000] 1f06 14080 mtdblock6 (driver?)
[ 0.665000] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

最佳答案

由内核初始化的模块的 init 例程(当它们被
静态链接到内核中)被包装在一个 initcall() 宏中,该宏指示
在启动序列中时,它们应该运行。

请参阅包含文件:include/linux/init.h 以获取宏列表及其顺序。

那里指定的顺序是:

  • early_initcall
  • pure_initcall
  • core_initcall
  • postcore_initcall
  • arch_initcall
  • 子系统初始化调用
  • fs_initcall
  • rootfs_initcall
  • device_initcall
  • 延迟初始化调用

  • 其中大多数都有一个“initcall_sync() 阶段,用于等待完成
    该阶段内的所有模块初始化例程。宏用于构建
    每个阶段的函数指针表,按顺序调用 do_initcalls() .

    如果使用“module_init()”来封装初始化函数,那么
    默认情况下,initcall() 将调用置于初始化的“设备”阶段。
    在该阶段中,项目按链接顺序排序。这意味着
    该表是按遇到的函数的顺序创建的
    由链接器。

    您可以将初始化移动到较早的阶段,方法是更改
    initcall 宏包装了模块初始化函数,但要小心,因为
    各个模块之间存在顺序依赖关系。另一种方法
    更改初始化顺序(在一个阶段内)将是调整链接
    内核中模块的顺序。

    关于linux-kernel - Linux如何确定模块init调用的顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10368837/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com