技術討論區 > Embedded 討論版
[教學] linuxrc 實作剖析
thyme:
linuxrc 實作剖析
本篇背景知識:linuxrc, busybox, initrd, bootloader(lilo or grub)
linuxrc 有何特異功能,請自行研究,本篇只說明如何應用。
linuxrc 通常在 initrd.img 內出現,由於此時所有檔案系統皆未掛載,
所以相關的 shell、binary、library 都要先包在裡面,甚至一些 kernel
可能沒有編譯進去的 modules 都要放在 initrd.img內。
如果你只使用一個 initrd.img 當成檔案系統的全部,沒有要把 root /
改成硬碟的 partition 的話,那就不需要 linuxrc,而且,我看 2.4.20
的 soruce,有一段是判斷,如果你的 root 是 ramdisk ,就不執行 linuxrc。
本篇測試的 kernel 都是 2.4.20 ,所以不同的版本,可能稍有不同。
先來看看一段很簡單的 linuxrc (本內容抄自 mdk 10.0)
--- 代碼: ---
#!/bin/nash
insmod /lib/jbd.ko
insmod /lib/ext3.ko
mount -t proc /proc /proc
mkdevices /dev
mount -t sysfs none /sys
mkrootdev /dev/root
umount /sys
echo 0x0100 > /proc/sys/kernel/real-root-dev
mount -o defaults --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
handledevfs
umount /initrd/proc
--- 程式碼結尾 ---
nash是很小的 shell ,剛好把 linuxrc 需要的功能都放進去,
所以我們就選擇它了。
--- 代碼: ---echo 0x0100 > /proc/sys/kernel/real-root-dev
--- 程式碼結尾 ---
是告訴 kernel ,我們的 root 是掛在第0個 ramdisk 上,
可以查一下
--- 代碼: ---ll /dev/rd/0
brw------- 1 root root 1, 0 1月 1 1970 /dev/rd/0
--- 程式碼結尾 ---
若是 /dev/hda8 則是 0x308,查一下
--- 代碼: ---ll hda8
brw-r----- 1 root root 3, 8 9月 9 2002 hda8
--- 程式碼結尾 ---
那個 3 及 8 就是你在 mknod /dev/hda8 b 3 8 中的 3 及 8,
不過,記得要轉成十六進位就是。
在 bootloader 中的 root=/dev/xxx 會傳到 /dev/root,
所以你要把 bootloader 內的 root=/dev/xxx 視為你的 root ,
就要用 mount 把它 mount 成 root 就成了。
再來是很多人的疑問,root 不是早被 initrd 掛用了嗎?沒錯,
所以我們要用 pivot_root 來改一下,
--- 代碼: ---pivot_root /sysroot /sysroot/initrd
--- 程式碼結尾 ---
這個的意思是,原來的 root / 改由 /sysroot 來做 root / ,
而目前的 initrd 就改成掛在 /sysroot/initrd 底下,
這邊注意一下,initrd.img 內的 /sysroot, 及一般硬碟內的 /initrd
都是寫死的目錄,所以你把它們砍了,就開不了機唷!
如果我們不管 bootloader 傳入 root= 是何方神聖,我們就是要指定
/dev/hda8,也可以這麼做:
--- 代碼: ---
#!/bin/nash
mount -t proc /proc /proc
echo 0x308 > /proc/sys/kernel/real-root-dev
--- 程式碼結尾 ---
因為 kernel 預設會去跑 /sbin/init ,你都告訴它是 /dev/hda8 了,
它就會自己去抓來跑。
再來就是比較複雜一點的,NFS boot,由於比較複雜些,我們改用 busybox
的 sh 來用,當然,這個 initrd.img 的大小也會大很多。
--- 代碼: ---
#!/bin/sh
mount -t proc proc /proc
echo 0x100 > /proc/sys/kernel/real-root-dev
insmod mii
insmod via-rhine
insmod sunrpc
insmod lockd
insmod nfs
ifconfig eth0 192.168.0.88
route add default gw 192.168.0.1
[ -x /sbin/portmap ] && /sbin/portmap
mount -t nfs 192.168.0.2:/nfs /sysroot
killall portmap
pivot_root /sysroot /sysroot/initrd
--- 程式碼結尾 ---
其中 192.168.0.88 是本地 ip,192.168.0.1 是指 router,
192.168.0.2是指 NFS server 及其開於 /nfs 的目錄。
這個 NFS boot 的做法和第一個很像,只是要事先準備好連線工作,
最後把把 root 切換過去就成了。
要注意一點,這些工作都要在 linuxrc 內做,如果你留在 rc.sysinit 來
做就來不及了,會啟動不了唷!切記!切記!
再來,變化一下,如果你的 root file system 是一個 ext2 image file
放在 /dev/hda1 的 /root_fs.img ,也可以直接拿來開機,
--- 代碼: ---
#!/bin/sh
mount -t proc proc /proc
echo 0x100 > /proc/sys/kernel/real-root-dev
mkdir /mnt
mount /dev/hda1 /mnt
mknod /dev/loop0 b 7 0
losetup /dev/loop0 /mnt/root_fs.img
mount /dev/loop0 /sysroot
pivot_root /sysroot /sysroot/initrd
--- 程式碼結尾 ---
--
本文章自由轉載,需註明作者及出處
V-ezlinux:
請教個問題etc是不能獨立的他跟/ 不能分開做成ramdisk後如何讓他重開後是設定後的檔案
thyme:
--- 引述: "V-ezlinux" ---請教個問題etc是不能獨立的他跟/ 不能分開做成ramdisk後如何讓他重開後是設定後的檔案
--- 引用結尾 ---
作法一:用 link 方式,事先 link 到 data 區。
作法二:在 rc.sysinit(或許你叫 rcS) 於開機時,把資料 copy 進來。
作法三:你可以在 linuxrc 內,就事先把 /etc 掛載在其他的地方。
作法四:在 rc.sysinit 用 bind 方式重新掛載 /etc 例如:
--- 代碼: ---
mount -n --bind /xxx/etc /etc
--- 程式碼結尾 ---
作法N:自己發揮。
V-ezlinux:
感謝..可是應該說我整個os都在ram0 也就是說( /dev/ram0 === / )...裡頭有etc可是是預設的 hdX1 上有etc hdx2有var 我測試將您說的那一段放在rc.local裡做測試mount /dev/hda1 config 也就是我ramdisk裡有config資料夾在mount -n --bind /config /etc ..可是他寫的etc還是寫到ram裡頭去耶他並沒有寫到hdX1上...有一些不了解還請大大說明一下...希望我的說明我的環境您可以了解架構跟floppy一樣將整個file system放到ram0上跑...只是希望設定好了的東西重開機還在不用一直重新設定...
thyme:
--- 引述: "V-ezlinux" ---感謝..可是應該說我整個os都在ram0 也就是說( /dev/ram0 === / )...裡頭有etc可是是預設的 hdX1 上有etc hdx2有var 我測試將您說的那一段放在rc.local裡做測試mount /dev/hda1 config 也就是我ramdisk裡有config資料夾在mount -n --bind /config /etc ..可是他寫的etc還是寫到ram裡頭去耶他並沒有寫到hdX1上...有一些不了解還請大大說明一下...希望我的說明我的環境您可以了解架構跟floppy一樣將整個file system放到ram0上跑...只是希望設定好了的東西重開機還在不用一直重新設定...
--- 引用結尾 ---
你是先跑 mount /dev/hda1 /config
還是先跑 mount -n --bind /config /etc
這應該有分別吧...
照你作法,不用這麼複雜,
在 linuxrc 內,就先 mount /dev/hda1 /etc 即可。
導覽
[0] 文章列表
[#] 下頁
前往完整版本