天天看點

用QEMU搭建arm開發環境之四:編譯ramdisk,啟動檔案系統1.RAMDISK簡介 2.用BusyBox建立RAMDISK 3.QEMU啟動核心加RAMDISK加挂載檔案系統

1.RAMDISK簡介

1.1   什麼是Ram Disk

Ram Disk 就是将記憶體中的一塊區域作為實體磁盤來使用的一種技術。

對于使用者來說,可以把RAM disk與通常的硬碟分區(如/dev/hda1)同等對待來使用。

1.2    Ramdisk與硬碟分區的不同

RAM disk不适合作為長期儲存檔案的媒體,掉電後Ramdisk的内容會随記憶體内容的消失而消失。

RAM disk的其中一個優勢是它的讀寫速度高,記憶體盤的存取速度要遠快于目前的實體硬碟,可以被用作需要高速讀寫的檔案。

注意:在2.6版本後,Ramdisk的這一作用開始被tmpfs(Virtual memory file system support)取代。   

1.3    系統啟動中Ramdisk的作用

系統盤中通常有一些檔案是希望被保護起來的,不希望被使用者修改,是以這些檔案最好是儲存在一種隻讀分區上。ramdisk通常被制作成一個鏡像,在uboot啟動的時候,加載到記憶體中而不是直接使用這個鏡像.這樣無論使用者怎麼修改這個記憶體中的檔案,再次啟動的時候又會恢複到最初的狀态.

1.4    日常使用中Ramdisk的作用

記憶體盤對于儲存加密資料來說是一個福音,因為我們如果将加密的檔案解密到普通磁盤的話,即使我們随後删除了解密檔案,資料仍然會留在磁盤上。這樣是非常不安全的。而對于 RamDisk 來說,沒有這樣的問題。假設有幾個檔案要頻繁的使用,你如果将它們加到記憶體當中,程式運作速度會大副提高,因為記憶體的讀寫速度遠高于硬碟。

2.用BusyBox建立RAMDISK

對Busybox而言無論是是制作成上一章所需的檔案系統還是本章所需的ramdisk,所需的檔案大體上是一樣的(這樣說的原因是通常ramdisk不是啟動的終點,ramdisk啟動成功後還需要跳轉到磁盤或者其他存儲媒體上的下一級系統的啟動檔案).

是以我們直接使用剛才做好的檔案系統image檔案來制作ramdisk(當然你也可以用busybox的編譯結果制作ramdisk).

sudo mount rootfs.ext3 mnt
cd mnt
find . | cpio -o -H newc | gzip -9 > ../ramdisk.gz
cd ..
sudo umount mnt
           

ramdisk.gz就是做好的ramdisk檔案.我們用下面的指令來啟動:

qemu-system-arm -M vexpress-a9 -m 512M -kernel zImage -dtb vexpress-v2p-ca9.dtb -initrd ramdisk.gz -append "root=/dev/ram0 clocksource=pit rw console=tty0 rdinit=/linuxrc"

上面指令中rdinit是指定ramdisk的啟動檔案,我們現在是選擇/linuxrc,參數root=/dev/ram0是選擇ramdisk作為root節點.console=tty0是選擇控制台為序列槽0,我們的核心編譯選擇了CONFIG_FRAMEBUFFER_CONSOLE=y,是以可以在螢幕上直接顯示控制台并操作.

3.QEMU啟動核心加RAMDISK加挂載檔案系統

到這裡我們雖然可以啟動ramdisk了但是我們沒有跳轉到檔案系統,是以我們需要修改上面的ramdisk來跳轉到其他存儲媒體的檔案系統(我們暫時還是以我們剛才制作的buzybox的檔案系統為例,後面最後一章會講如何啟動加載ubuntu的檔案系統.

這時候我們不能繼續使用busybox預設的linuxrc作為啟動檔案了,因為它時間上是一個busybox的連接配接,我們需要在根目錄建立一個init的檔案.init檔案的内容如下:

#!/bin/sh
echo
echo "###########################################################"
echo "## THis is a init script example in ramdisk              ##"
echo "###########################################################"
echo
 
PATH="/bin:/sbin:/usr/bin:/usr/sbin"
 
if [ ! -f "/bin/busybox" ];then
  echo "cat not find busybox in /bin dir, exit"
  exit 1
fi
 
BUSYBOX="/bin/busybox"
 
echo "build root filesystem..."
$BUSYBOX --install -s
 
if [ ! -d /proc ];then
  echo "/proc dir not exist, create it..."
  $BUSYBOX mkdir /proc
fi
echo "mount proc fs..."
$BUSYBOX mount -t proc proc /proc
 
if [ ! -d /dev ];then
  echo "/dev dir not exist, create it..."
  $BUSYBOX mkdir /dev
fi
# echo "mount tmpfs in /dev..."
# $BUSYBOX mount -t tmpfs dev /dev
 
$BUSYBOX mkdir -p /dev/pts
echo "mount devpts..."
$BUSYBOX mount -t devpts devpts /dev/pts
 
if [ ! -d /sys ];then
  echo "/sys dir not exist, create it..."
  $BUSYBOX mkdir /sys
fi
echo "mount sys fs..."
$BUSYBOX mount -t sysfs sys /sys
 
echo "/sbin/mdev" > /proc/sys/kernel/hotplug
echo "populate the dev dir..."
$BUSYBOX mdev -s
 
echo "dev filesystem is ok now, log all in kernel kmsg" >> /dev/kmsg
 
echo "you can add some third part driver in this phase..." >> /dev/kmsg
echo "begin switch root directory to sd card" >> /dev/kmsg
 
$BUSYBOX mkdir /newroot
if [ ! -b "/dev/mmcblk0" ];then
  echo "can not find /dev/mmcblk0, please make sure the sd \
    card is attached correctly!" >> /dev/kmsg
  echo "drop to shell" >> /dev/kmsg
  $BUSYBOX sh
else
  $BUSYBOX mount /dev/mmcblk0 /newroot
  if [ $? -eq 0 ];then
    echo "mount root file system successfully..." >> /dev/kmsg
  else
    echo "failed to mount root file system, drop to shell" >> /dev/kmsg
    $BUSYBOX sh
  fi
fi
 
# the root file system is mounted, clean the world for new root file system
echo "" > /proc/sys/kernel/hotplug
$BUSYBOX umount -f /proc
$BUSYBOX umount -f /sys
$BUSYBOX umount -f /dev/pts
# $BUSYBOX umount -f /dev
 
echo "enter new root..." >> /dev/kmsg
exec $BUSYBOX switch_root -c /dev/console /newroot /linuxrc
 
if [ $? -ne 0 ];then
  echo "enter new root file system failed, drop to shell" >> /dev/kmsg
  $BUSYBOX mount -t proc proc /proc
  $BUSYBOX sh
fi
           

上面檔案中這一句指定了下一步跳轉到新檔案系統的中linuxrc檔案,如果啟動檔案不一樣,需要修改這個腳本的這一句話.

exec $BUSYBOX switch_root -c /dev/console /newroot /linuxrc

儲存後檔案系統大概是這個樣子的:

bin  init  linuxrc  sbin  usr
           

然後适當調整啟動指令如下:

qemu-system-arm -M vexpress-a9 -m 512M -kernel zImage -dtb vexpress-v2p-ca9.dtb -initrd ramdisk.gz -append "root=/dev/ram0 clocksource=pit rw console=tty0 rdinit=/init" -sd rootfs.ext3

其中rdinit=/init把ramdisk的啟動檔案改為了剛才我們寫的腳本init,然後-sd rootfs.ext3把我們上一章做好的檔案系統以sd的形式挂載到了目前的qemu系統.

運作後你會看到如下的資訊:

begin switch root directory to sd card
EXT4-fs (mmcblk0): mounting ext3 file system using the ext4 subsystem
EXT4-fs (mmcblk0): recovery complete
EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Opts: (null)
mount root file system successfully...
enter new root...
Please press Enter to activate this console. 
           

從日志中你可以看出,首先啟動ramdisk的init,然後挂載了sd卡,然後從把更目錄切換到了sd卡,然後從sd卡啟動了linuxrc檔案.

當然你也可以使用下面的指令:

qemu-system-arm -M vexpress-a9 -m 512M -kernel zImage -dtb vexpress-v2p-ca9.dtb -initrd ramdisk.gz -append "root=/dev/ram0 clocksource=pit rw console=ttyAMA0 rdinit=/init" -sd rootfs.ext3 -serial stdio -smp 4

其中console=ttyAMA0指定了新的序列槽,這個序列槽是和HOST相通的,然後用-serial stdio把序列槽連接配接到了我們的标準輸入輸出端口(也就是我們現在敲指令的地方),然後-smp 4制定了我們使用4核的處理器.啟動成功後你就可以在HOST的console輸入指令了.

鳴謝:本文部分内容來自下面的連結,感謝相關作者的貢獻.如侵權或需要删除請聯系我.

https://blog.csdn.net/wys7250578/article/details/9045237

https://blog.csdn.net/love_gaohz/article/details/41041781

https://www.jianshu.com/p/c0d8107f161e

繼續閱讀