作者 主題: [教學] linuxrc 實作剖析  (閱讀 31658 次)

0 會員 與 1 訪客 正在閱讀本文。

thyme

  • 老人組
  • 俺是博士!
  • *****
  • 文章數: 1281
    • 檢視個人資料
[教學] linuxrc 實作剖析
« 於: 2005-08-15 16:14 »
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

  • 憂鬱的高中生
  • ***
  • 文章數: 128
    • 檢視個人資料
linuxrc
« 回覆 #1 於: 2005-08-19 09:35 »
請教個問題etc是不能獨立的他跟/ 不能分開做成ramdisk後如何讓他重開後是設定後的檔案

thyme

  • 老人組
  • 俺是博士!
  • *****
  • 文章數: 1281
    • 檢視個人資料
Re: linuxrc
« 回覆 #2 於: 2005-08-19 10:05 »
引述: "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

  • 憂鬱的高中生
  • ***
  • 文章數: 128
    • 檢視個人資料
hi
« 回覆 #3 於: 2005-08-19 13:35 »
感謝..可是應該說我整個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

  • 老人組
  • 俺是博士!
  • *****
  • 文章數: 1281
    • 檢視個人資料
Re: hi
« 回覆 #4 於: 2005-08-19 14:32 »
引述: "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 即可。

V-ezlinux

  • 憂鬱的高中生
  • ***
  • 文章數: 128
    • 檢視個人資料
ramdisk
« 回覆 #5 於: 2005-08-20 23:44 »
哈感謝說明,是我寫錯造成不行後來抓到問題了..現在要將voip server的功能放進去有啥問題在來請教...哈感謝萬分有機會請您吃個飯摟....萬能的天神哈~說真的喔

ericshei

  • 全區板主
  • 俺是博士!
  • *****
  • 文章數: 2257
    • 檢視個人資料
[教學] linuxrc 實作剖析
« 回覆 #6 於: 2005-10-11 16:34 »
有些問題請指點:

還境RH9

pivot_root /sysroot /sysroot/initrd

執行如上指令後,當下是否就切換到新的root filesystem中了? 若然最後一行的"umount /initrd/proc"就是umount原initrd中的proc了,對吧?

另外/sysroot/initrd中的initrd敍述應該是對應到,真正root filesystem中的/initrd目錄了,對吧?

另外關於mkrootdev的用途,man nash之後了解的是,若沒有指定kernel的root=參數就使用/proc/sys/kernel/real-root-dev的值,這個部份,我在一搬的partition上測試是沒問題的,但在LVM上似乎行不通? 設定如下:

kernel 開機設為root=/dev/vg00/rootreiserfs

linuxrc 內容如下:

引用
echo "Loading scsi_mod.o module"
insmod /lib/scsi_mod.o
echo "Loading sd_mod.o module"
insmod /lib/sd_mod.o
echo "Loading BusLogic.o module"
insmod /lib/BusLogic.o
echo "Loading lvm-mod.o module"
insmod /lib/lvm-mod.o
echo "Loading jbd.o module"
insmod /lib/jbd.o
echo "Loading ext3.o module"
insmod /lib/ext3.o
echo "Loading reiserfs.o module"
insmod /lib/reiserfs.o
echo Mounting /proc filesystem
mount -t proc /proc /proc
echo Creating block devices
mkdevices /dev
echo Scanning logical volumes
vgscan
echo Activating logical volumes
vgchange -ay
echo Creating root device
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
echo Mounting root filesystem
#mount -o defaults --ro -t reiserfs /dev/vg00/rootreiserfs /sysroot
mount -o defaults --ro -t reiserfs /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc


不過若將linuxrc中mount rootfilesystem的部份改成如下就可以:

mount -o defaults --ro -t reiserfs /dev/vg00/rootreiserfs /sysroot
但前提不能將echo 0x0100 > /proc/sys/kernel/real-root-dev給註解掉.
這個部份不知是不是我對mkrootdev的理解還有問題?

而我在標準RH9的LVM上,看它的linuxrc也是直接做指定,沒有用mkrootdev所產生的/dev/root,且也是有對/proc/sys/kernel/real-root-dev做指定.

望前輩們指點!  ^^

thyme

  • 老人組
  • 俺是博士!
  • *****
  • 文章數: 1281
    • 檢視個人資料
[教學] linuxrc 實作剖析
« 回覆 #7 於: 2005-10-11 18:15 »
引述: "ericshei"
有些問題請指點:

還境RH9

pivot_root /sysroot /sysroot/initrd

執行如上指令後,當下是否就切換到新的root filesystem中了? 若然最後一行的"umount /initrd/proc"就是umount原initrd中的proc了,對吧?

另外/sysroot/initrd中的initrd敍述應該是對應到,真正root filesystem中的/initrd目錄了,對吧?


這我沒有詳究,實作看看結果就是了。

引用

不過若將linuxrc中mount rootfilesystem的部份改成如下就可以:

mount -o defaults --ro -t reiserfs /dev/vg00/rootreiserfs /sysroot
但前提不能將echo 0x0100 > /proc/sys/kernel/real-root-dev給註解掉.
這個部份不知是不是我對mkrootdev的理解還有問題?



我的苦力經驗是,如果你的 real-root-dev 不是 0x100,
那麼,你的 pivot_root 會做白工,還是跳回原來 real-root-dev,
然後告訴你不能 mount rootfs -_-|||
0x100 指的是 ramdisk ,也就是目前 mount initrd 的 /dev/ram0。

mkrootdev LVM
也許 mkrootdev 沒有支援這個 device,或是 grub 傳不進這個 device,
也或許是 kernel 一開機沒有建立這個 device ,這要測一下才知道。

ericshei

  • 全區板主
  • 俺是博士!
  • *****
  • 文章數: 2257
    • 檢視個人資料
[教學] linuxrc 實作剖析
« 回覆 #8 於: 2005-10-12 09:22 »
引述: "thyme"
引述: "ericshei"
有些問題請指點:

還境RH9

pivot_root /sysroot /sysroot/initrd

執行如上指令後,當下是否就切換到新的root filesystem中了? 若然最後一行的"umount /initrd/proc"就是umount原initrd中的proc了,對吧?

另外/sysroot/initrd中的initrd敍述應該是對應到,真正root filesystem中的/initrd目錄了,對吧?


這我沒有詳究,實作看看結果就是了。

嗯.實作結果,的確如此!  ^^

引用
引用

不過若將linuxrc中mount rootfilesystem的部份改成如下就可以:

mount -o defaults --ro -t reiserfs /dev/vg00/rootreiserfs /sysroot
但前提不能將echo 0x0100 > /proc/sys/kernel/real-root-dev給註解掉.
這個部份不知是不是我對mkrootdev的理解還有問題?



我的苦力經驗是,如果你的 real-root-dev 不是 0x100,
那麼,你的 pivot_root 會做白工,還是跳回原來 real-root-dev,
然後告訴你不能 mount rootfs -_-|||
0x100 指的是 ramdisk ,也就是目前 mount initrd 的 /dev/ram0。

mkrootdev LVM
也許 mkrootdev 沒有支援這個 device,或是 grub 傳不進這個 device,
也或許是 kernel 一開機沒有建立這個 device ,這要測一下才知道。


關於LVM的device file執行到linuxrc中的vgscan及vgchange -ay 才會出現.

多謝指點.   :wink: