Linux系統啟動詳解(二),linux系統啟動詳解

來源:互聯網
上載者:User

Linux系統啟動詳解(二),linux系統啟動詳解

上節講到了Linux啟動大體流程,及grub的作用,本節主要扯扯initramfs的那些事,並且通過簡單修改initramfs,將整體作業系統運行到了記憶體中。

3       initramfs3.1     簡述

  在2.4核心中initrd為boot loader initialized RAM Disk,linux啟動前boot loader先將initrd檔案解壓,並載入到記憶體中。boot loader載入核心後,會先運行initrd,再switch_root到真正root fs。

  在2.6核心中將initrd升級為initramfs,與initrd相比其作用相同,但是initramfs流程更加簡潔,即解壓initramfs後,運行init指令碼,所以任務交由init指令碼來完成。

更多initrd與initramfs的說明可參見文獻[3]。

[3]:Linux2.6核心的Initrd機制解析http://www.ibm.com/developerworks/cn/linux/l-k26initrd/

3.2     init基本流程

  initramfs的真正作用載入硬體模組和檔案系統模組,用於切換到root device上的真正的root fs上。當然由於root fs應該支援存在於md或者dm裝置上,所以在initramfs期間也會載入md和dm模組,如果md編譯進行了核心的話,從載入的模組中是查看不到的。

以下是通過在initramfs中的init檔案中添加log,分析一個大概的開機流程,非細節。

1)         解壓並載入initramfs到記憶體後,當前root fs就是initramfs,所以/下所有檔案都來源於initramfs。

2)         通過掛載/proc和/sys;mknod建立基本的裝置/dev/console、/dev/null等。

3)         udev規則對硬體進行掃描,載入對應模組,建立對應裝置,對於grub.conf中設定的root裝置,若建立成功,則會在/dev/下建立/dev/root的連結指向對應真實裝置。

4)         與此同時,無限迴圈判斷/dev/root是否已存在,若不存在,再次執行所有udev規則,嘗試是否有新硬體已準備就緒,判斷40次後(約20秒),仍未找到,則報出“no root device fonud, sleep forever”

5)         通過root device掛載真正的root fs。

6)         判斷/proc目錄是否存在,作為root fs已掛載成功的標準(此時的/proc僅僅是個空目錄)。

7)         判斷真正的root fs的init指令碼是否存在,一般是/sbin/init

8)         root fs已掛載到/sysroot目錄後,執行switch_root /sysroot /sbin/init。

9)         switch_root命令執行後,initramfs的任務全部完成,切換到真正的root fs,開始執行/sbin/init

3.3     initramfs過程中的模組載入情況

begin init:

Opening /proc/modules: No such file or directory

 

pre udev:

Module                  Size  Used by

 

after udev:

Module                  Size  Used by

sd_mod                 37157  0

crc_t10dif              1507  1 sd_mod

sr_mod                 16162  0

cdrom                  39769  1 sr_mod

mptspi                 16537  0

mptscsih               35302  1 mptspi

mptbase                91106  2 mptspi,mptscsih

scsi_transport_spi     26117  1 mptspi

pata_acpi               3667  0

ata_generic             3611  0

ata_piix               22588  0

dm_mod                 76856  0

 

after mount root fs, before switch root:

Module                  Size  Used by

ext4                  353883  1

mbcache                 7918  1 ext4

jbd2                   88969  1 ext4

sd_mod                 37157  2

crc_t10dif              1507  1 sd_mod

sr_mod                 16162  0

cdrom                  39769  1 sr_mod

mptspi                 16537  1

mptscsih               35302  1 mptspi

mptbase                91106  2 mptspi,mptscsih

scsi_transport_spi     26117  1 mptspi

pata_acpi               3667  0

ata_generic             3611  0

ata_piix               22588  0

dm_mod                 76856  0

3.4     initramfs的解壓&&壓縮

1、  解壓:

-bash-4.1# file initramfs-2.6.32-71.el6.5.vsds.x86_64.img

initramfs-2.6.32-71.el6.5.vsds.x86_64.img: gzip compressed data, from Unix, last modified: Tue Dec 18 17:25:14 2012, max compression

# gzip檔案格式,所以需要先mv為gz檔案

-bash-4.1# mv initramfs-2.6.32-71.el6.5.vsds.x86_64.img initramfs-2.6.32-71.el6.5.vsds.x86_64.img.gz

-bash-4.1# file initramfs-2.6.32-71.el6.5.vsds.x86_64.img

initramfs-2.6.32-71.el6.5.vsds.x86_64.img: ASCII cpio archive (SVR4 with no CRC)

-bash-4.1# gunzip initramfs-2.6.32-71.el6.5.vsds.x86_64.img.gz

initramfs-2.6.32-71.el6.5.vsds.x86_64.img

#此時為cpio格式

-bash-4.1# mkdir initramfs

-bash-4.1# cd initramfs

-bash-4.1# cpio -id ../initramfs

initramfs/                                 initramfs-2.6.32-71.el6.5.vsds.x86_64.img 

-bash-4.1# cpio -id < ../initramfs-2.6.32-71.el6.5.vsds.x86_64.img

72953 blocks

2、  壓縮:

-bash-4.1# find . | cpio -c -o > ../initramfs-2.6.32-71.el6.5.vsds.x86_64.img

72953 blocks

-bash-4.1# gzip ../initramfs-2.6.32-71.el6.5.vsds.x86_64.img

-bash-4.1# cp ../initramfs-2.6.32-71.el6.5.vsds.x86_64.img.gz /boot

3.5     執行個體---將整個作業系統運行在記憶體

  以下使用方式情節並未真正應用,以下純屬個人理解,供參考。

3.5.1  優點 && 缺點

1、優點:

1)         運行速度更快。開機後,由於系統運行在記憶體,運行速度要更快。

2)         檔案系統不會損壞。系統異常斷電,或者其它破壞操作,不會引起作業系統損壞。

3)         節省儲存介質空間。作業系統可以進行壓縮後存放在可儲存介質中(壓縮率約80%),甚至可以存放在網路環境上,開機後,解壓再到記憶體。

4)         便於多台系統統一升級升級。若系統壓縮檔存放在網路環境上,那麼檔案升級,使用這個檔案的任意台裝置升級過程就僅僅是重啟就可以做到。

2、缺點:

1)         開機速度略慢。由於啟動過程需要將作業系統解壓到記憶體,會略慢一點,約10 ~ 20秒不明顯。

2)         root fs無法儲存資料。由於系統運行在記憶體,重啟後新儲存的丟失。因此,一般需要儲存資料的分區單獨掛載一個非易失的介質上。

3)         記憶體要求更大。由於記憶體固定部分會劃分一個ram disk,用於運行作業系統。對於作業系統就需要900M空間的應用,記憶體2G就不足以支撐整個系統。

4)         更新系統較麻煩。對於需要頻率更改系統的環境,若要生效,需要重新製作壓縮檔,較麻煩。

3.5.2  應用情境

  目前嵌入式系統大多使用此方案,應該是基於其較小的儲存空間,及無使用者寫入資料要求而決定的。(本人不是做嵌入式的,純屬個人猜測哈)

3.5.3  實現思路

思路一:就是把整體系統做成initramfs。(未測試)

  initramfs就是一個小檔案系統,也是開機第一個載入的檔案系統,所以把整體系統都做成initramfs,那麼系統啟動只需要2個檔案即可,一是核心vmlinux;二是initramfs。

  也就是說在initramfs最後要切換到真正的root fs時,不切換到了,直接運行系統中的/sbin/init。

  但是initramfs可能會達到300M(root fs900M左右),boot loader會不會需要載入很長時間?

思路二:在initramfs運行過程中,將壓縮的系統解壓並複製到記憶體中運行

  在上節已說明initramfs其實就是執行一個init指令碼,簡單修改指令碼流程。當尋到到root device裝置後,將掛載root device掛載到/sysroot修改為,掛載root device到其它掛載點,再從root device中找到之前製作的壓縮的系統檔案,將檔案解壓到ramdisk中,掛載ramdisk到/sysroot,再切換到真正的root fs。

3.5.4  實現代碼

  以下僅根據思路二為基本,完成的一個簡單模型。

  將系統檔案解壓並複製到記憶體,那麼先得將真正的root fs製作為一個系統檔案,再通過initramfs的過程將其載入到記憶體。

1、  root fs檔案ramlinux.img.gz的製作。

  開始只將參考資料[2]中檔案製作為了ramlinux.img.gz(壓縮後約80M,解壓後給不到200M),開機系統就panic,想必是應該缺少檔案導致,所以,就將整個/下所有檔案都製作到ramdisk.img.gz中,系統正常運行。

  製作ramdisk.img.gz的指令碼為mkrootfs.sh如下:

#!/bin/sh

rootfs="/mnt/ram"

umount $rootfs

rm -rf $rootfs

 

# make ram disk and mount

dd if=/dev/zero of=/dev/ram bs=1M count=900

echo y | mkfs.ext2 /dev/ram

mkdir $rootfs

mount -o loop /dev/ram $rootfs

 

# cp file to ram disk

pre_dir="/"

#pre_dir="/mnt/sdf1/"

 

# all file in dir cp to ram disk

cpdir=(bin boot cgroup etc home lib lib64 media opt sbin selinux srv usr var)

for dir_i in ${cpdir[@]}

do

         echo "cp -av $pre_dir$dir_i $rootfs"

         cp -av $pre_dir$dir_i $rootfs

done

 

# just mkdir, not cp file

mkdir=(proc sys tmp mnt root)

for dir_j in ${mkdir[@]}

do

         echo "mkdir $rootfs/$dir_j"

         mkdir $rootfs/$dir_j

done

 

# create dev device

mkdir $rootfs/dev

dev=`find /dev`

for dev_i in ${dev[@]}

do

         if [ $dev_i = "/dev/ram" -o $dev_i = "/dev" ]

         then

                   echo "find $dev_i pass........................................... "

                   continue

         fi

         echo "cp -R $dev_i $rootfs/dev"

         cp -R $dev_i $rootfs/dev

done

 

# do ramlinux.img from ram disk

umount $rootfs

dd if=/dev/ram of=/mnt/bigspace/ramlinux.img bs=1M

gzip /mnt/bigspace/ramlinux.img

2、  initramfs載入root fs檔案ramlinux.img.gz。

  initramfs掛載真正的root fs,是通過執行initramfs的mount目錄下的*.sh來完成的,在mount目錄下加入98mount-ramdisk.sh,移除99mount-root.sh(原掛載root device到/sysroot的指令碼)。由98mount-ramdisk.sh來完成系統檔案的解壓,及掛載。

  98mount-ramdisk.sh如下:

#!/bin/sh

echo "Mount root device for get img file"

mount -o defaults --rw /dev/root /mnt

echo "zcat img file to ram"

/bin/zcat /mnt/root/ramlinux.img.gz > /dev/ram

umount /mnt

echo "mount -o loop /dev/ram /sysroot"

mount -o loop /dev/ram /sysroot

echo "ls /sysroot"

/bin/ls /sysroot/

[ -d "/sysroot/proc" ] || echo "proc not exist 5555555555555555555........"

3、  完成以上步驟後,將initramfs解壓,拷貝98mount-ramdisk.sh到mount目錄下,刪除99mount-root.sh,重建initramfs,覆蓋/boot下的原檔案,重啟即生效。

4、  其它注意。由於解壓ramlinux.img需要zcat命令,但此命令initramfs中未加入,因此,還需要從系統中拷貝zcat命令到initramfs的bin目錄下。(拷貝命令前,需要通過ldd /bin/zcat查看該命令是否有對應動態連結程式庫,如果有要一併cp-R到initramfs的對應目錄下,否則僅拷貝命令,命令是無法執行的)

5、  重啟後的系統內容:

a)         重啟後,系統從掛載資訊即可看出當前系統已運行在記憶體中,並且touch的新檔案,重啟無未儲存,掛載資訊如下:

-bash-4.1# df -h

Filesystem            Size  Used Avail Use% Mounted on

/dev/sda1             886M  886M     0 100% /

tmpfs                 2.0G   52M  1.9G   3% /dev/shm

/dev/sda2             146M   32M  106M  24% /var/log

 (/的掛載裝置應該不是/dev/sda1,應該是df命令在當前模型下顯示的問題,應該是/dev/ram,由於只是簡單模型搭建,很多配置未修改成導致。)

b)         /dev/sda1是grub.conf中設定的root device,也是ramlinux.img檔案真正儲存的介質。

-bash-4.1# cat /boot/grub/grub.conf

# grub.conf generated by anaconda

#

# Note that you do not have to rerun grub after making changes to this file

# NOTICE:  You do not have a /boot partition.  This means that

#          all kernel and initrd paths are relative to /, eg.

#          root (hd0,0)

#          kernel /boot/vmlinuz-version ro root=/dev/sda1

#          initrd /boot/initrd-[generic-]version.img

#boot=/dev/sda

default=0

timeout=5

splashimage=(hd0,0)/boot/grub/splash.xpm.gz

hiddenmenu

title SkySAN Storage System (2.6.32-71.el6.5.vsds.x86_64)

         root (hd0,0)

         kernel /boot/vmlinuz-2.6.32-71.el6.5.vsds.x86_64 ro root=UUID=212c95a4-56d0-44fc-93ce-73b5f3e8cf2a rd_NO_LUKS rd_NO_LVM rd_NO_MD rd_NO_DM LANG=en_US.UTF-8 SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=us

         initrd /boot/initramfs-2.6.32-71.el6.5.vsds.x86_64.img

3.6     init指令碼中加入log資訊

  在理解init指令碼過程中,為了更深入的理解init的作用,及當前環境狀態,往往需要列印一些我們自己需要的資訊,在列印到螢幕的同時,如果可能儲存檔案,便於多次閱讀更好。

方法如下:

logfile="/tmp/logfile"

# tee用於將輸出到螢幕的資訊,同時儲存檔案,-a:不覆蓋檔案原內容,相當於>>

echo "begin init -------------------------------------------------------" 2>&1 | tee -a $logfile

lsmod 2>&1 | tee -a $logfile

sleep 5

……

#在swith_root前,將檔案拷貝到/dev/目錄下,切換到root fs後,可以保留。

cp $logfile /dev/

exec switch_root "$NEWROOT" "$INIT" $initargs

……

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.