修改initrd,創建一個微型的linux系統

創建一個MiniLinux:

  通過對RamDisk(Initrd)分析,現在瞭解了initrd的主要原理及工作流程,爲了加深對該過程的理解,下面使用initrd創建一個微型的linux系統,也更加深對linux開機過程的原理性瞭解:並用腳本實現該過程;

 環境:宿主機:RedHat 5.4 內核:2.6.18

 要求:首先實現最基本的啓動,正常啓動後給用戶一個shell;後期拓展,需要實現將根文件系統掛載爲RW,實現命令:mount、umount、vi、ls、touch、mkdir等。也可以後期按照需求添加各項功能,逐漸豐富;

1. 配置所需的環境:新增硬盤/dev/sdb(大小512M~1G綽餘)、建立所需目錄(這裏假定新增的硬盤爲sdb)

  1. # mkdir  -v  /mnt/sysroot  
  2. # mkdir  -v  /mnt/boot 
  3. # mkdir  -v  /tmp/init 
  4.  

  注:在虛擬機裏面添加硬盤時將硬盤放到自己容易找到的位置,最好不用默認位置;

2. 對新硬盤分區,格式化後掛載到/mnt目錄下的適當位置

  1. # fdisk  /dev/sdb   (將硬盤分爲兩個區,第一個100M作爲boot分區,第二個作爲根分區) 
  2. # partproble  /dev/sdb   
  3. # mkfs -t ext3 /dev/sdb1 
  4. # mkfs -t ext3 /dev/sdb2  
  5. # mount /dev/sdb1 /mnt/boot 
  6. # mount /dev/sdb2 /mnt/sysroot 
  7. # mount  (查看掛載是否成功) 
  8.  

3. 拷貝內核文件到相應的位置,並且解包initrd

  1. # cp /boot/vmlinuz-`uname -r`.img /mnt/boot/vmlinuz 
  2. # cd /tmp/init 
  3. # zcat /boot/initrd.2.6.18-164.el5.img | cpio -id  &> /dev/null 
  4.  

4. 修改RamDisk內容:

  1. # sed -i s/\(mkrootdev.*ro[[:space:]]\).*/\1sda2/g /tmp/init 
  2.  

  上步驟中將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文件修改後示例:

  1. #!/bin/nash 
  2. mount -t proc /proc /proc 
  3. setquiet 
  4. echo Mounting proc filesystem 
  5. echo Mounting sysfs filesystem 
  6. mount -t sysfs /sys /sys 
  7. echo Creating /dev 
  8. mount -o mode=0755 -t tmpfs /dev /dev 
  9. mkdir /dev/pts 
  10. mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts 
  11. mkdir /dev/shm 
  12. mkdir /dev/mapper 
  13. echo Creating initial device nodes 
  14. mknod /dev/null c 1 3 
  15. mknod /dev/zero c 1 5 
  16. mknod /dev/systty c 4 0 
  17. mknod /dev/tty c 5 0 
  18. mknod /dev/console c 5 1 
  19. mknod /dev/ptmx c 5 2 
  20. mknod /dev/rtc c 10 135 
  21. mknod /dev/tty0 c 4 0 
  22. mknod /dev/tty1 c 4 1 
  23. mknod /dev/tty2 c 4 2 
  24. mknod /dev/tty3 c 4 3 
  25. mknod /dev/tty4 c 4 4 
  26. mknod /dev/tty5 c 4 5 
  27. mknod /dev/tty6 c 4 6 
  28. mknod /dev/tty7 c 4 7 
  29. mknod /dev/tty8 c 4 8 
  30. mknod /dev/tty9 c 4 9 
  31. mknod /dev/tty10 c 4 10 
  32. mknod /dev/tty11 c 4 11 
  33. mknod /dev/tty12 c 4 12 
  34. mknod /dev/ttyS0 c 4 64 
  35. mknod /dev/ttyS1 c 4 65 
  36. mknod /dev/ttyS2 c 4 66 
  37. mknod /dev/ttyS3 c 4 67 
  38. echo Setting up hotplug. 
  39. hotplug 
  40. echo Creating block device nodes. 
  41. mkblkdevs 
  42. echo "Loading uhci-hcd.ko module" 
  43. insmod /lib/uhci-hcd.ko  
  44. echo "Loading ohci-hcd.ko module" 
  45. insmod /lib/ohci-hcd.ko  
  46. echo "Loading ehci-hcd.ko module" 
  47. insmod /lib/ehci-hcd.ko  
  48. mount -t usbfs /proc/bus/usb /proc/bus/usb 
  49. echo "Loading jbd.ko module" 
  50. insmod /lib/jbd.ko  
  51. echo "Loading ext3.ko module" 
  52. insmod /lib/ext3.ko  
  53. echo "Loading scsi_mod.ko module" 
  54. insmod /lib/scsi_mod.ko  
  55. echo "Loading sd_mod.ko module" 
  56. insmod /lib/sd_mod.ko  
  57. echo "Loading scsi_transport_spi.ko module" 
  58. insmod /lib/scsi_transport_spi.ko  
  59. echo "Loading mptbase.ko module" 
  60. insmod /lib/mptbase.ko  
  61. echo "Loading mptscsih.ko module" 
  62. insmod /lib/mptscsih.ko  
  63. echo "Loading mptspi.ko module" 
  64. insmod /lib/mptspi.ko  
  65. echo "Loading dm-mod.ko module" 
  66. insmod /lib/dm-mod.ko  
  67. echo Waiting for driver initialization. 
  68. stabilized --hash --interval 250 /proc/scsi/scsi 
  69. echo Making device-mapper control node 
  70. mkdmnod 
  71. mkblkdevs 
  72. echo Creating root device. 
  73. mkrootdev -t ext3 -o defaults,ro /dev/sda2  (這裏請按照自己使用的情況進行修改,我的下一步實驗環境爲單盤,但是如實驗者的環境非但盤,請依照次序進行調整)
  74. echo Mounting root filesystem. 
  75. mount /sysroot 
  76. echo Setting up other filesystems. 
  77. setuproot 
  78. echo Switching to new root and running init. 
  79. switchroot 
  80.  

5. 重新打包修改好的鏡像到相應位置:

  1. # find . | cpio --quiet -H newc -o |gzip -9 -n > /mnt/boot/initrd.gz 
  2. # cd /mnt/boot/ ; ls    (查看生成鏡像)
  3.  

  命令解釋:找本目錄下修改好的的全部文件,用管道送給cpio進行打包,使用靜默模式,-H制定創建的歸檔文件類型爲newc(是一種支持的文件個數的inode號大於65535的文件模型),並且用 -o 進行輸出,輸出的流用gzip壓縮,使用最大壓縮比9,創建出的壓縮文件輸出至/mnt/boot路徑下

6. 安裝grub到新加的硬盤上:

  1. # grub-install --root-directory=/mnt  /dev/sdb 
  2.  注: --root-directory指定安裝的位置,並且命令會自己尋找目錄下的boot目錄來進行安裝;

7. 編輯生成grub配置文件
   安裝後缺少grub.conf文件,需要手動建立,也可以將宿主機上的文件拷貝後進行相應的修改:
    格式如下:

  1. timeout=5 
  2. default=0 
  3.  
  4. title MyLinux 
  5.     root (hd0,0) 
  6.     kernel /vmlinuz ro root=/dev/sda2 
  7.     initrd /initrd.gz 
  8.  

8. 在根分區sysroot目錄下創建基本目錄:

  1. # cd /mnt/sysroot 
  2. # mkdir -pv bin dev etc lib sbin sys tmp proc tmp 
  3. # chmod 1777 ./tmp  
  4.  

9.  拷貝基本的/sbin/init及/bin/bash文件到相應的位置(這兩個是最基本的,也可附加其他的命令,自己擴展):

  1. # cp /bin/bash  /mnt/sysroot/bin 
  2. # cp /sbin/init  /mnt/sysroot/sbin 
  3.  

10. 拷貝相應命令的lib庫文件:
  (注意某些庫文件是鏈接文件,需要將鏈接及源文件一塊拷過去。)

  1. # ldd /bin/bash
  2.  
  3. # ldd /sbin/init
  4.  
  5. # cp -d /lib/libsepol.so.1 /mnt/sysroot/lib/ 
  6.  

如下ldd命令顯示的信息:其中有庫文件的全路徑;根據路徑拷貝庫文件:

 注:linux-gate.so.1 是一個虛擬的庫標誌,所以不需要拷貝;

   cp命令的 -d 參數可以拷貝指定的原文件(區別源文件),若拷貝的是一個鏈接,則拷貝的是該鏈接文件;若拷貝鏈接文件時不加-d參數會使拷貝的時庫鏈接的源文件,這樣可能造成某些共享性庫的錯誤;

 拷貝後,查看,發現有源文件需要拷貝,再拷貝鏈接文件指向的源文件:


 
  在庫完全鏈接正確後不會再有顏色顯示警告;
  上面只是拷貝一部分庫的實例,在拷貝時需要對照拷貝進去所有的庫文件;

11. 建立init的配置文件/etc/inittab (bash腳本文件注意給予相應的權限)

  1. #  vim /mnt/sysroot/etc/inittab 
  2.  文件編輯格式如下: 
  3.  
  4. id:3:initdefault:  (設置系統默認運行級別)
  5. si::sysinit:/etc/rc.d/rc.sysinit  (置系統初始化腳本位置)
  6.  


12. 建立系統調用系統初始化時需要的/etc/rc.d/rc.sysinit腳本:

  1. # vim  /mnt/sysroot/etc/rc.d/rc.sysinit 
  2.   編輯文件格式如下: 
  3. #!/bin/bash
  4. echo -e “\tWelcome to \033[31mMyLinux\033[0m.” 
  5. /bin/bash 
  6.  

  :設置進入系統初始化界面需要的東西。可以不輸出信息,但是需要運行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路徑下,否則會造成出錯;

  1. #!/bin/bash 
  2. #Author: Mo 
  3. #Date & Time: 2011-03-10 20:19:20 
  4. #Description: auto create a minilinux  
  5. #Version : 1.2.1 
  6.  
  7. tmpdir=`mktemp -d /tmp/init.XXXX` 
  8. disk=/dev/sdb 
  9. sysroot=/mnt/sysroot 
  10. sysboot=/mnt/boot 
  11.  
  12. # Partition the disk 
  13. echo "n 
  14. 13 
  15. 14 
  16. +1000M 
  17. W" | fdisk ${disk} &>/dev/null 
  18. wait 
  19.  
  20. #update /proc/partitions 
  21. /sbin/partprobe ${disk} 
  22. sleep 5 
  23. # making file system 
  24. /sbin/mkfs -t ext3 ${disk}1 
  25. wait 
  26. /sbin/mkfs -t ext3 ${disk}2 
  27. wait 
  28.  
  29. mkdir -pv ${sysboot} ${sysroot} 
  30.  
  31. #update /proc/partitions 
  32. /sbin/partprobe &> /dev/null 
  33. sleep 5 
  34. #mount disk 
  35. /bin/mount -t ext3 ${disk}1  ${sysboot} 
  36. /bin/mount -t ext3 ${disk}2  ${sysroot} 
  37. wait 
  38.  
  39. #kernel; 
  40. cp /boot/vmlinuz-`uname -r` /mnt/boot/vmlinuz 
  41. sync 
  42.  
  43. #create initrd; 
  44. cd ${tmpdir} 
  45. /bin/zcat /boot/initrd-*.img | cpio -id  &>/dev/null 
  46. sed -i  s@mkrootdev.*@'mkrootdev -t ext3 -o defaults,ro /dev/sda2'@  ./init 
  47. sync 
  48. find . | cpio --quiet -H newc -o | gzip -9 -n >/mnt/boot/initrd.gz 
  49. wait 
  50.  
  51. #grub 
  52. grub-install --root-directory=/mnt ${disk} &>/dev/null 
  53. touch ${sysboot}/grub.conf 
  54. echo "default=0 
  55. timeout=2 
  56. title  MyLinux 
  57. root (hd0,0) 
  58. kernel  /vmlinuz 
  59. initrd  /initrd.gz" > /mnt/boot/grub/grub.conf 
  60. sync 
  61.  
  62. #create basic directorys in sysroot 
  63. mkdir  -p $sysroot/{etc/rc.d,dev,lib,bin,sbin,proc,sys,tmp}  &>/dev/null 
  64. chmod 1777 ${sysroot}/tmp 
  65. wait 
  66.  
  67. #cp libs 
  68. #bash ls mount bash vi 
  69. autolib.sh  -s init
  70. sleep 1 
  71. /root/bin/autolib.sh -s bash
  72. sleep 1
  73. autolib.sh  -s ls 
  74. sleep 1 
  75. #/tmp/autolib.sh  -s vim 
  76. autolib.sh  -s mount 
  77. sleep 1 
  78. autolib.sh  -s umount 
  79. sleep 1 
  80. chmod a+x ${sysroot}/{bin,sbin}/* 
  81. wait 
  82.  
  83. #create file /etc/inittab 
  84. echo "id:3:initdefault: 
  85. si::sysinit:/etc/rc.d/rc.sysinit" >${sysroot}/etc/inittab 
  86.  
  87. #create file  /etc/rc.d/rc.sysinit 
  88. echo '#!/bin/bash
  89. mount -n -o remount,rw /dev/sda2 /  
  90. echo -e "\tWelcome to \033[31mMy Linux\033[0m" 
  91. /bin/bash' > ${sysroot}/etc/rc.d/rc.sysinit 
  92. chmod a+x ${sysroot}/etc/rc.d/rc.sysinit 
  93.  
  94. echo "All Done....... 
  95. Then you can test the miniLinix." 

 

拓展參考:

http://www.ibm.com/developerworks/cn/linux/l-initrd.html(IBM上面用busybox實現了一個精簡的initrd)

 整理過程,難免出錯,希望共同探討;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章