2012-04-28 72 views
20

我有一個設備與SPI閃存存儲我想使用該閃存設備上的UBIFS文件系統作爲我的rootfs。我面臨的問題是UBI模塊在SPI模塊初始化之前初始化。因此,當UBI加載時,它不能附加到我告訴它的UBI設備上(通過內核命令行),所以沒有rootfs。以下控制檯輸出說明了這一點。Linux如何確定模塊初始化調用的順序?

我已經深入到源碼中看到init/main.c有一個do_initcalls()函數,它只是簡單地調用一個函數指針列表。這些函數指針指向內核中內置模塊的全部功能。這些函數指針被放置在內核二進制文件的特殊部分,所以這個順序是在編譯時選擇的。但是,我還沒有弄清楚這個訂單是如何確定的。

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

我被判遷移(因此),因爲儘管這可能不是需要修改源代碼,它至少需要Kbuild欺騙。另外[so]是專家的地方。我懷疑你不應該依賴於特定的命令,並且UBI驅動程序不應該嘗試訪問任何設備,直到它被告知要安裝某些東西。 – Gilles 2012-04-28 22:37:00

+0

[LINUX:靜態鏈接模塊加載順序]的可能重複(http://stackoverflow.com/questions/5669647/linux-order-of-statically-linked-module-loading)這表明您需要確保模塊以所需的初始化順序出現在makefile的(樹)中。 – 2012-04-29 19:44:30

+0

使用'EPROBE_DEFER'可能會有一個替代解決方案;我會檢查一下。 – 2012-05-02 15:48:42

回答

0

我可能是錯的,所以請檢查這是否正確。
嘗試編譯所需的所有驅動程序作爲模塊(M),並將模塊以正確的順序裝入/ etc/modules,這可以解決您的問題。 準確地說,因爲你在之前做了這個你的rootfs被掛載,所以上面的步驟應該在initram磁盤上完成。 (我有一個類似的情況,我需要加載一些模塊以正確的順序,以便能夠解密FS)

希望這有助於
CiaoCiao
塞爾吉奧

+1

將它們作爲單獨的模塊編譯是不行的,因爲它會將模塊放在根文件系統上。我所說的這些模塊是安裝根文件系統的模塊。 – 2012-04-29 14:45:01

+0

@ ShawnJ.Goff:我編輯了這篇文章,因爲我意識到我忘了提及一個重要的細節。 initramfs部分。 :) – sergico 2012-04-29 14:46:47

+0

initramfs不是一個選項 - 它增加了我的構建的大小不可接受的數量。 – 2012-04-29 14:48:50

32

初始化程序的模塊由內核初始化(當它們是靜態鏈接到內核的 時)包含在initcall()宏中,該宏指示 在啓動順序中應該運行。

請參閱包含文件:include/linux/init.h以獲取宏列表及其排序。

的順序指定的有:

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

大多數這些具有「initcall_sync()階段,該階段用於該階段內等待的 完成所有模塊的初始化例程。這些宏用於爲每個階段構建一個函數指針表,這些函數指針由 do_initcalls()依次調用。

如果使用「module_init()」來包裝初始化函數,那麼默認情況下 initcall()會將調用置於初始化的「device」階段。 在該階段中,項目按鏈接順序排序。這意味着 該表格是由鏈接器遇到的 函數的順序創建的。

您可以通過更改哪個 initcall宏包裝模塊初始化函數來將初始化移至早期階段,但要小心,因爲 在各個模塊之間存在順序依賴關係。 改變初始化順序(在一個階段中)的另一種方法是調整內核中模塊的鏈接 順序。

0

@Tim伯德已經回答了 - 我想說明如何更改順序,一個模塊: -

pure_initcall(fn)   --> Loaded first 
core_initcall(fn)   
core_initcall_sync(fn)  
postcore_initcall(fn)  
postcore_initcall_sync(fn) 
arch_initcall(fn)   
arch_initcall_sync(fn)  
subsys_initcall(fn)  
subsys_initcall_sync(fn) 
fs_initcall(fn)   
fs_initcall_sync(fn)  
rootfs_initcall(fn)  
device_initcall(fn)  
device_initcall_sync(fn) 
late_initcall(fn)   
late_initcall_sync(fn) --> Loaded last 

Usage - Replace fn by the module init function pointer, example for i2c core driver: 
....... 
postcore_initcall(i2c_init); // To delay i2c core loading use subsys_initcall(i2c_init)     
module_exit(i2c_exit); 
.......