Linux如何确定模块init调用的顺序? [英] How does Linux determine the order of module init calls?

查看:193
本文介绍了Linux如何确定模块init调用的顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我已经潜入到源码中,看到 init / main.c 有一个 do_initcalls()函数,只需调用一个函数指针列表。那些函数指针指向内核内置的模块的所有 module_init()函数。那些函数指针被放置在内核二进制的特殊部分中,所以在编译时选择这个顺序。但是,我还没有弄清楚这个顺序是如何确定的。

  [0.482500] UBI错误:ubi_init:UBI错误:无法初始化UBI,错误-19 
[0.492500] atmel_spi atmel_spi.0:使用dma0chan0(tx)和dma0chan1(rx)进行DMA传输
[0.500000] atmel_spi atmel_spi.0:Atmel SPI控制器(0xf0000000)
[0.507500] m25p80 spi0.1:mx25l25635e(32768 Kbytes)
[0.512500]在jedec_flash上创建7个MTD分区:
[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 Wat启用chdog(心跳= 15秒,nowayout = 0)
[0.607500] TCP立方注册
[0.615000] VFS:无法打开根设备ubi0:root0或未知块(0,0)
[0.622500]请附上正确的root =启动选项;这里是可用的分区:
[0.630000] 1f00 128 mtdblock0(驱动程序?)
[0.635000] 1f01 256 mtdblock1(驱动程序)
[0.640000] 1f02 128 mtdblock2(驱动程序)
[0.645000] 1f03 2048 mtdblock3(driver?)
[0.650000] 1f04 2048 mtdblock4(driver?)
[0.655000] 1f05 14080 mtdblock5(driver?)
[0.660000] 1f06 14080 mtdblock6 (驱动程序?)
[0.665000]内核紧急 - 不同步:VFS:无法挂载根fs在未知块(0,0)


解决方案

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



请参阅include文件:include / linux / init.h宏列表及其排序。



指定的订单是:




  • early_initcall

  • pure_initcall

  • core_initcall

  • postcore_initcall

  • arch_initcall

  • subys_initcall

  • fs_initcall

  • rootfs_initcall

  • device_initcall

  • late_initcall



大多数都有一个initcall_sync()阶段,用于等待
中所有模块初始化例程的完成那个阶段宏用于构建每个阶段的
a表的函数指针,它们按顺序由
do_initcalls() $调用。



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



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


I have a device with SPI flash storage I'd like to use an UBIFS filesystem on that flash device as my rootfs. The problem I'm facing is that the UBI module initializes before the SPI module initializes. Because of this, when UBI loads, it cannot attach to the UBI device that I've told it to (via the kernel command line), so there is no rootfs. The console output below illustrates this.

I've been diving into the source enough to see that init/main.c has a do_initcalls() function that simply calls a list of function pointers. Those function pointers point to the all the module_init() functions of the modules that are built-in to the kernel. Those function pointers are placed in a special section in the kernel binary, so this order is chosen at compile-time. However, I haven't yet figured out how that order is determined.

    [    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)

解决方案

The init routines for a module that is initialized by the kernel (when they are statically linked into the kernel) are wrapped in an initcall() macro that indicates when in the startup sequence they should be run.

See the include file: include/linux/init.h for a list of the macros and their ordering.

The order specified there is:

  • early_initcall
  • pure_initcall
  • core_initcall
  • postcore_initcall
  • arch_initcall
  • subsys_initcall
  • fs_initcall
  • rootfs_initcall
  • device_initcall
  • late_initcall

Most of these have an "initcall_sync() phase, which is used to wait for completion of all module initialization routines within that phase. The macros are used to build a table of function pointers for each phase, which are called in sequence by do_initcalls().

If "module_init()" is used to wrap the initialization function, then by default initcall() puts the call in the "device" phase of initialization. Within that phase, the items are ordered by link order. This means that the table is created by the order of the functions as they are encountered by the linker.

You may be able to move an initialization to an earlier phase, by changing which initcall macro wraps the modules initialization function, but be careful because there are order dependencies between the various modules. Another method of changing the initialization order (within a phase) would be to adjust the link order for the module in the kernel.

这篇关于Linux如何确定模块init调用的顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆