建立一個MiniLinux:html
經過對RamDisk(Initrd)分析,如今瞭解了initrd的主要原理及工做流程,爲了加深對該過程的理解,下面使用initrd建立一個微型的linux系統,也更加深對linux開機過程的原理性瞭解:並用腳本實現該過程;node
環境:宿主機:RedHat 5.4 內核:2.6.18linux
要求:首先實現最基本的啓動,正常啓動後給用戶一個shell;後期拓展,須要實現將根文件系統掛載爲RW,實現命令:mount、umount、vi、ls、touch、mkdir等。也能夠後期按照需求添加各項功能,逐漸豐富;shell
1. 配置所需的環境:新增硬盤/dev/sdb(大小512M~1G綽餘)、創建所需目錄(這裏假定新增的硬盤爲sdb)vim
- # mkdir -v /mnt/sysroot
- # mkdir -v /mnt/boot
- # mkdir -v /tmp/init
注:在虛擬機裏面添加硬盤時將硬盤放到本身容易找到的位置,最好不用默認位置;bash
2. 對新硬盤分區,格式化後掛載到/mnt目錄下的適當位置網絡
- # fdisk /dev/sdb (將硬盤分爲兩個區,第一個100M做爲boot分區,第二個做爲根分區)
- # partproble /dev/sdb
- # mkfs -t ext3 /dev/sdb1
- # mkfs -t ext3 /dev/sdb2
- # mount /dev/sdb1 /mnt/boot
- # mount /dev/sdb2 /mnt/sysroot
- # mount (查看掛載是否成功)
3. 拷貝內核文件到相應的位置,而且解包initrdapp
- # cp /boot/vmlinuz-`uname -r`.img /mnt/boot/vmlinuz
- # cd /tmp/init
- # zcat /boot/initrd.2.6.18-164.el5.img | cpio -id &> /dev/null
4. 修改RamDisk內容:ide
- # sed -i s/\(mkrootdev.*ro[[:space:]]\).*/\1sda2/g /tmp/init
上步驟中將RanDisk解壓出來init文件中的」mkrootdev -t ext3 -o defaults,ro /dev/VolGroup00/LogVol00」項修改成」mkrootdev -t ext3 -o defaults,ro sda2」;而且能夠根據實際需求,將該文件中不須要加載的dm-mirror、dm-zero、dm-snapshrot項註釋或刪掉;固然爲了更加精簡鏡像文件的大小,能夠到對應的/lib文件夾下刪除相應的文件;測試
initrd文件修改後示例:
- #!/bin/nash
- mount -t proc /proc /proc
- setquiet
- echo Mounting proc filesystem
- echo Mounting sysfs filesystem
- mount -t sysfs /sys /sys
- echo Creating /dev
- mount -o mode=0755 -t tmpfs /dev /dev
- mkdir /dev/pts
- mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts
- mkdir /dev/shm
- mkdir /dev/mapper
- echo Creating initial device nodes
- mknod /dev/null c 1 3
- mknod /dev/zero c 1 5
- mknod /dev/systty c 4 0
- mknod /dev/tty c 5 0
- mknod /dev/console c 5 1
- mknod /dev/ptmx c 5 2
- mknod /dev/rtc c 10 135
- mknod /dev/tty0 c 4 0
- mknod /dev/tty1 c 4 1
- mknod /dev/tty2 c 4 2
- mknod /dev/tty3 c 4 3
- mknod /dev/tty4 c 4 4
- mknod /dev/tty5 c 4 5
- mknod /dev/tty6 c 4 6
- mknod /dev/tty7 c 4 7
- mknod /dev/tty8 c 4 8
- mknod /dev/tty9 c 4 9
- mknod /dev/tty10 c 4 10
- mknod /dev/tty11 c 4 11
- mknod /dev/tty12 c 4 12
- mknod /dev/ttyS0 c 4 64
- mknod /dev/ttyS1 c 4 65
- mknod /dev/ttyS2 c 4 66
- mknod /dev/ttyS3 c 4 67
- echo Setting up hotplug.
- hotplug
- echo Creating block device nodes.
- mkblkdevs
- echo "Loading uhci-hcd.ko module"
- insmod /lib/uhci-hcd.ko
- echo "Loading ohci-hcd.ko module"
- insmod /lib/ohci-hcd.ko
- echo "Loading ehci-hcd.ko module"
- insmod /lib/ehci-hcd.ko
- mount -t usbfs /proc/bus/usb /proc/bus/usb
- echo "Loading jbd.ko module"
- insmod /lib/jbd.ko
- echo "Loading ext3.ko module"
- insmod /lib/ext3.ko
- echo "Loading scsi_mod.ko module"
- insmod /lib/scsi_mod.ko
- echo "Loading sd_mod.ko module"
- insmod /lib/sd_mod.ko
- echo "Loading scsi_transport_spi.ko module"
- insmod /lib/scsi_transport_spi.ko
- echo "Loading mptbase.ko module"
- insmod /lib/mptbase.ko
- echo "Loading mptscsih.ko module"
- insmod /lib/mptscsih.ko
- echo "Loading mptspi.ko module"
- insmod /lib/mptspi.ko
- echo "Loading dm-mod.ko module"
- insmod /lib/dm-mod.ko
- echo Waiting for driver initialization.
- stabilized --hash --interval 250 /proc/scsi/scsi
- echo Making device-mapper control node
- mkdmnod
- mkblkdevs
- echo Creating root device.
- mkrootdev -t ext3 -o defaults,ro /dev/sda2 (這裏請按照本身使用的狀況進行修改,個人下一步實驗環境爲單盤,可是如實驗者的環境非但盤,請依照次序進行調整)
- echo Mounting root filesystem.
- mount /sysroot
- echo Setting up other filesystems.
- setuproot
- echo Switching to new root and running init.
- switchroot
5. 從新打包修改好的鏡像到相應位置:
- # find . | cpio --quiet -H newc -o |gzip -9 -n > /mnt/boot/initrd.gz
- # cd /mnt/boot/ ; ls (查看生成鏡像)
命令解釋:找本目錄下修改好的的所有文件,用管道送給cpio進行打包,使用靜默模式,-H制定建立的歸檔文件類型爲newc(是一種支持的文件個數的inode號大於65535的文件模型),而且用 -o 進行輸出,輸出的流用gzip壓縮,使用最大壓縮比9,建立出的壓縮文件輸出至/mnt/boot路徑下
6. 安裝grub到新加的硬盤上:
- # grub-install --root-directory=/mnt /dev/sdb
- 注: --root-directory指定安裝的位置,而且命令會本身尋找目錄下的boot目錄來進行安裝;
7. 編輯生成grub配置文件
安裝後缺乏grub.conf文件,須要手動創建,也能夠將宿主機上的文件拷貝後進行相應的修改:
格式以下:
- timeout=5
- default=0
- title MyLinux
- root (hd0,0)
- kernel /vmlinuz ro root=/dev/sda2
- initrd /initrd.gz
8. 在根分區sysroot目錄下建立基本目錄:
- # cd /mnt/sysroot
- # mkdir -pv bin dev etc lib sbin sys tmp proc tmp
- # chmod 1777 ./tmp
9. 拷貝基本的/sbin/init及/bin/bash文件到相應的位置(這兩個是最基本的,也可附加其餘的命令,本身擴展):
- # cp /bin/bash /mnt/sysroot/bin
- # cp /sbin/init /mnt/sysroot/sbin
10. 拷貝相應命令的lib庫文件:
(注意某些庫文件是連接文件,須要將連接及源文件一塊拷過去。)
- # ldd /bin/bash
- # ldd /sbin/init
- # cp -d /lib/libsepol.so.1 /mnt/sysroot/lib/
以下ldd命令顯示的信息:其中有庫文件的全路徑;根據路徑拷貝庫文件:
注:linux-gate.so.1 是一個虛擬的庫標誌,因此不須要拷貝;
cp命令的 -d 參數能夠拷貝指定的原文件(區別源文件),若拷貝的是一個連接,則拷貝的是該連接文件;若拷貝連接文件時不加-d參數會使拷貝的時庫連接的源文件,這樣可能形成某些共享性庫的錯誤;
拷貝後,查看,發現有源文件須要拷貝,再拷貝連接文件指向的源文件:
在庫徹底連接正確後不會再有顏色顯示警告;
上面只是拷貝一部分庫的實例,在拷貝時須要對照拷貝進去全部的庫文件;
11. 創建init的配置文件/etc/inittab (bash腳本文件注意給予相應的權限)
- # vim /mnt/sysroot/etc/inittab
- 文件編輯格式以下:
- id:3:initdefault: (設置系統默認運行級別)
- si::sysinit:/etc/rc.d/rc.sysinit (置系統初始化腳本位置)
12. 創建系統調用系統初始化時須要的/etc/rc.d/rc.sysinit腳本:
- # vim /mnt/sysroot/etc/rc.d/rc.sysinit
- 編輯文件格式以下:
- #!/bin/bash
- echo -e 「\tWelcome to \033[31mMyLinux\033[0m.」
- /bin/bash
:設置進入系統初始化界面須要的東西。能夠不輸出信息,可是須要運行bash,進入bash環境
注:在實際系統中init讀取inittab文件,按照文件中的配置依次進行下面工做:
inittdefault 定義系統默認運行級別;
rc.sysint 初始化系統的網絡,文件系統等
/etc/rc.d/rc N 執行相應的運行相應級別下的服務腳本
mingetty 提供用戶登錄認證,在認證成功後自動調用/bin/bash,爲用戶提供接口
/etc/X11/prefdm -nodeamon 若是有設置,開啓X界面
可是在該小型linux中,沒有登陸認證功能,因此須要在系統初始化完成後顯式的爲用戶提供shell。
13. 關閉宿主機系統;新建一個虛擬機,硬盤選爲剛纔建立的硬盤,開機測試;
用shell腳本實現上述建立過程:
系統環境跟上述描述一致,須要先新建硬盤,而且過程當中使用了我文章《腳本,自動查找並拷貝庫》中的腳原本自動拷貝庫,須要將調用的腳本路徑添加到PATH路徑下,不然會形成出錯;
- #!/bin/bash
- #Author: Mo
- #Date & Time: 2011-03-10 20:19:20
- #Description: auto create a minilinux
- #Version : 1.2.1
- tmpdir=`mktemp -d /tmp/init.XXXX`
- disk=/dev/sdb
- sysroot=/mnt/sysroot
- sysboot=/mnt/boot
- # Partition the disk
- echo "n
- p
- 1
- 1
- 13
- n
- p
- 2
- 14
- +1000M
- W" | fdisk ${disk} &>/dev/null
- wait
- #update /proc/partitions
- /sbin/partprobe ${disk}
- sleep 5
- # making file system
- /sbin/mkfs -t ext3 ${disk}1
- wait
- /sbin/mkfs -t ext3 ${disk}2
- wait
- mkdir -pv ${sysboot} ${sysroot}
- #update /proc/partitions
- /sbin/partprobe &> /dev/null
- sleep 5
- #mount disk
- /bin/mount -t ext3 ${disk}1 ${sysboot}
- /bin/mount -t ext3 ${disk}2 ${sysroot}
- wait
- #kernel;
- cp /boot/vmlinuz-`uname -r` /mnt/boot/vmlinuz
- sync
- #create initrd;
- cd ${tmpdir}
- /bin/zcat /boot/initrd-*.img | cpio -id &>/dev/null
- sed -i s@mkrootdev.*@'mkrootdev -t ext3 -o defaults,ro /dev/sda2'@ ./init
- sync
- find . | cpio --quiet -H newc -o | gzip -9 -n >/mnt/boot/initrd.gz
- wait
- #grub
- grub-install --root-directory=/mnt ${disk} &>/dev/null
- touch ${sysboot}/grub.conf
- echo "default=0
- timeout=2
- title MyLinux
- root (hd0,0)
- kernel /vmlinuz
- initrd /initrd.gz" > /mnt/boot/grub/grub.conf
- sync
- #create basic directorys in sysroot
- mkdir -p $sysroot/{etc/rc.d,dev,lib,bin,sbin,proc,sys,tmp} &>/dev/null
- chmod 1777 ${sysroot}/tmp
- wait
- #cp libs
- #bash ls mount bash vi
- autolib.sh -s init
- sleep 1
- /root/bin/autolib.sh -s bash
- sleep 1
- autolib.sh -s ls
- sleep 1
- #/tmp/autolib.sh -s vim
- autolib.sh -s mount
- sleep 1
- autolib.sh -s umount
- sleep 1
- chmod a+x ${sysroot}/{bin,sbin}/*
- wait
- #create file /etc/inittab
- echo "id:3:initdefault:
- si::sysinit:/etc/rc.d/rc.sysinit" >${sysroot}/etc/inittab
- #create file /etc/rc.d/rc.sysinit
- echo '#!/bin/bash
- mount -n -o remount,rw /dev/sda2 /
- echo -e "\tWelcome to \033[31mMy Linux\033[0m"
- /bin/bash' > ${sysroot}/etc/rc.d/rc.sysinit
- chmod a+x ${sysroot}/etc/rc.d/rc.sysinit
- echo "All Done.......
- Then you can test the miniLinix."
拓展參考:
http://www.ibm.com/developerworks/cn/linux/l-initrd.html(IBM上面用busybox實現了一個精簡的initrd)
整理過程,不免出錯,但願共同探討;