系統啓動掛載根文件系統時Kernel panic

系統啓動掛載根文件系統時Kernel panic

這類問題很常見,先總體介紹一下解決思路。
能出現讓人激動的的控制檯,那麼系統移植已經接近完成;但是不少人在最後一步出現問題。
要點如下:
1. 在正確的位置燒寫正確格式的文件系統映象:
2. 內核支持這種文件系統格式
3. 文件系統的內容要完備

上面說得簡單,一個個介紹。
1. 在正確的位置燒寫正確的文件系統映象:
(a). 正確的位置
嵌入式開發中,常通過bootloader燒寫文件系統映象,假設寫在flash的地址A處。
內核啓動時,顯然要從地址A處讀取文件系統,內核是怎麼知道的呢?通過命令行參數,比如“root=/dev/mtdblock2 ”。/dev/mtdblock2 又是怎麼和地址A對應上的呢?內核將flash劃分爲
幾個分區,這是在代碼中固定的。/dev/mtdblock2是第3個分區,它的開始地址必須是A。
在內核啓動時,可以看到這些分區的開始地址、結束地址,比如內核啓動時會有類似下面的信息:
Creating 3 MTD partitions on "NAND 64MiB 3,3V 8-bit":
0x00000000-0x00030000 : "bootloader"
0x00050000-0x00250000 : "kernel"
0x00250000-0x03ffc000 : "root"

對於上面的內核信息,/dev/mtdblock2對應root分區,開始地址爲0x00250000,使用bootloader寫文件系統映象時,燒寫的地址必須是0x00250000

所以,要保證3點:① bootloader燒到地址A,② 地址A是內核某個分區的開始地址,③ 命令行參數“root=/dev/mtdblockXXX ”是這個分區

(b). 正確格式的文件系統映象
不同的bootloader支持的燒寫的文件系統映象格式不同、使用的燒寫命令也可能不同,請注意這點。
另外,馬大哈們製作文件系統映象時,使用的工具也不要弄錯了。
最後,請保證這個文件系統映象是“真的燒寫了”,因爲如果flash只是擦除而沒有燒寫,它也是“正確的、可以掛接的文件系統”──有人碰到這個問題,我和他答非所問地折騰了很久。

2. 內核支持這種文件系統格式
配置內核時選上要支持的文件系統格式

1、2這兩個問題如果不能保證,內核啓動時會出現類似如下錯誤:
VFS: Cannot open root device "mtdblock2" or unknown-block(2,0)
Please append a correct "root=" boot option

如果1、2能保證,就可以掛接上文件系統,出現類似下面的字樣時,革命已經成功了80%:
VFS: Mounted root (cramfs filesystem) readonly.
Freeing init memory: 116K

3. 文件系統的內容要完備
掛接文件系統後,內核就會讀取、執行文件系統中的某個文件,通過它來啓動應用程序。這個文件要麼通過命令行參數“init=xxxx”來指定,要麼取默認的文件(下面說明)。
一般製作文件系統映象時,都是在一個目錄(假設目錄名爲rootfs)下放好各種東西:bin/,sbin/,lib/等目錄,etc/fstab等文件,然後將這個目錄製作爲文件系統映象。
可以想象,如果這個目錄中的東西不對、不全,即使製作出了文件系統映象,也只是能識別出來,掛接上去;但是啓動不了──所謂啓動,不就是執行文件系統中的程序嘛?
這時會有類似以下的錯誤:
Failed to execute /linuxrc.  Attempting defaults...
Kernel panic - not syncing: No init found.  Try passing init= option to kernel.

它說得很明顯,"Failed to execute /linuxrc"──執行/linuxrc失敗:
它爲什麼要執行/linuxrc,還不是因爲你在命令行中加入了“init=/linuxrc”這個參數。
它爲什麼會失敗?原因有二:
一、你製作文件系統映象時,rootfs目錄下有linuxrc這個文件嗎?
二、rootfs目錄的linuxrc文件是正確的嗎?
請好好確定這兩點,大多數是沒有linuxrc文件──linuxrc是busybox自動生成的,只要配置好就可以。
如果有linuxrc,那麼就是它無法執行了(解決方法在下面)。

不用linuxrc行不行?當然行!看看內核文件init/main.c,有如下字樣:
    run_init_process("/sbin/init");
    run_init_process("/etc/init");
    run_init_process("/bin/init");
    run_init_process("/bin/sh");
    panic("No init found.  Try passing init= option to kernel.");
就是說,它會依次嘗試執行/sbin/init、/etc/init、/bin/init、/bin/sh這些文件,都失敗後纔打印出錯信息"No init found.  Try passing init= option to kernel."。

所以,出現這個出錯信息時,就表明了沒有或是無法執行這些文件:命令行參數“init=xxxx”來指定的xxx文件、/sbin/init、/etc/init、/bin/init、/bin/sh。
一、請檢查你的rootfs目錄,看看這點些文件是否存在
二、使用file命令看看它們是什麼文件類型,是否可執行。
使用busybox時,這些文件是到/bin/busybox文件的鏈接,那就看看busybox的文件類型,可以使用下面的命令:
$ file linuxrc 
linuxrc: symbolic link to `bin/busybox'
$ file bin/busybox 
bin/busybox: ELF 32-bit LSB executable, ARM, version 1, for GNU/Linux 2.4.3, dynamically linked (uses shared libs), stripped

注意了:如果bin/busybox 是一個動態鏈接的文件,還要把它用到的庫複製到rootfs中。唉,越說越複雜了。這些庫在交叉編譯工具的相應目錄下,如果不知道,查google,否則再發帖。

最後一點,文件系統中各種配置文件、dev目錄也要正確。出現問題時再在這個帖子中說吧。這樣寫下去真是沒完沒了。

回到這個帖子,它的內核打印信息爲:
VFS: Mounted root (cramfs filesystem) readonly.
Freeing init memory: 116K
Failed to execute /linuxrc.  Attempting defaults...
Kernel panic - not syncing: No init found.  Try passing init= option to kernel.

說明文件系統掛接成功(VFS: Mounted root (cramfs filesystem) readonly.);
還說明/linuxrc不存在或者不可執行(Failed to execute /linuxrc.  Attempting defaults...);
但是樓主的意思是linuxrc已經有了,內容爲:
#!/bin/sh
echo "mount /etc as ramfs"
/bin/mount -n -t ramfs ramfs /etc
/bin/cp -a /mnt/etc/* /etc
echo "re-create the /etc/mtab entries"
# re-create the /etc/mtab entries
/bin/mount -f -t cramfs -o remount,ro /dev/mtdblock/3 /
/bin/mount -f -t ramfs ramfs /etc
exec /sbin/init

它是一個腳本,它的執行依賴於/bin/sh,問題轉爲:/bin/sh是否存在?是否可以執行?
用file命令看看它的類型、是否需要動態庫。
發佈了41 篇原創文章 · 獲贊 46 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章