目標
- 建置一個基本的 Ramdisk for arm,以便了解整個 file system 的開機流程。
- ramdisk 主要程式由 busybox 提供,並包含基本的設定檔。
- 建置平台為 Qemu: ARM Integrator/CP board 的模擬平台上。
Preview
- 參考之前 Linux 2.6 的 initramfs 機制,了解 initramfs 的觀念。
- Linux 2.6 核心將一個小的 ram-based initial root filesystem(initramfs) 包進核心,且若這個檔案系統包含一隻程式 /init,核心會將它當作第一隻程式執行。此時,找尋其他檔案系統並執行其他程式已不再是核心的問題,而是新程式的工作。
開機及初步 ramdisk
- 由於Linux 2.6 核心已將一個小的 ram-based initial root filesystem(initramfs) 包進核心,所以我們可以先建立一個假的 ramdisk,只包含 init 來測試是否 kernel boot 成功與否。Ref: Jserv's blog: 深入理解 Linux 2.6 的 initramfs 機制 (上)
mkdir hello-initramfs
cd hello-initramfs
vi init.c
arm-none-linux-gnueabi-gcc -static -o init init.c # 編成 static 省麻煩
file init # 確認編譯完成的檔案格式是否正確
#init: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.14, statically linked, not stripped
mkdir dev
cd dev
mknod -m 600 console c 5 1
cd ..- init.c, 將開機停在執行 /init 時,以驗証我們的動作是否成功
#include
int main()
{
printf("Hello World!\n");
sleep(9999);
return 0;
}
- init.c, 將開機停在執行 /init 時,以驗証我們的動作是否成功
- Build Kernel
- 取得最近的 kernel source,linux-2.6.26.3
- 嚐試用 kernel source 裡的 integrator_defconfig 編譯 kernel,但在測試時發現沒有任何反應,所以先從 qemu 網站上可以下載的 arm-test-0.2.tar.gz 裡取出 .config 來編譯。
- 修改 Makefile 以符合我們用的 cross compile
ARCH ?= arm
CROSS_COMPILE ?= arm-none-linux-gnueabi- - make menuconfig,記得選取 initramfs 並填上 path
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
(/home/ryan/qemu/hello-initramfs) Initramfs source file(s) - make zImage
- 測試: qemu-system-arm -kernel linux-2.6.26.3/arch/arm/boot/zImage。可以看見開機時有成功執行 Hello World! 這個 fake init
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
802.1Q VLAN Support v1.8 Ben Greear
All bugs added by David S. Miller
VFP support v0.3: implementor 41 architecture 1 part 10 variant 9 rev 0
Hello World!
- 以 busybox 建置 ramdisk,將 busybox 編譯為 static。
- 取得最新 soruce BusyBox 1.11.2
- 修改 Makefile
CROSS_COMPILE ?= arm-none-linux-gnueabi-
ARCH ?= arm - make menuconfig。記得選取 static libnary
[*] Build BusyBox as a static binary (no shared libs)
- make install。會在目錄下產生 _install 目錄,這也是待會我們要移進 ramdisk 的內容
- 檢查檔案格式
file _install/bin/busybox
#_install/bin/busybox: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.14, statically linked, stripped
- 建置初步 ramdisk
mkdir busybox-initramfs
cd busybox-initramfs/
cp -av ../busybox-1.11.2/_install/* .
ln -s sbin/init init
find ./ | cpio -o -H newc | gzip > ../busybox.initramfs.cpio.gz
cd .. - 啟動
qemu-system-arm -kernel linux-2.6.26.3/arch/arm/boot/zImage -initrd busybox.initramfs.cpio.gz
- 此時會一直 argue 缺少 device 。此時可是自建相關的 device node,則可正常啟動。
- 但我希望能由系統自行建立,所以先 copy arm_test 裡 file system 的 etc 目錄 來用,待之後再來分析流程。成功開機。
cd busybox-initramfs
cp ../arm-test/arm_root.img arm_root.img.gz
gunzip arm_root.img.gz
mkdir tmp
cd tmp
cpio -i -F ../arm_root.img
cp -av etc ../
touch mdev.conf # 這是因為開機時 complain 沒有這個檔,所以先做個假的。這是因為開始時有執行 mdev,而 mdev.conf 為它的設定檔。
mkdir root
cd ..
rm -rf arm_root.img tmp
find ./ | cpio -o -H newc | gzip > ../busybox.initramfs.cpio.gz
qemu-system-arm -kernel linux-2.6.26.3/arch/arm/boot/zImage -initrd busybox.initramfs.cpio.gz
開機流程剖析
- Linux kernel 在掛載 ramdisk 後,預設會尋找 /init 這隻程式,除非在内核傳遞参數裡有設置 init=/linuxrc 來指定要找的第一個程式。
- 目前 /init 是由 busybox 所提供的,其預設行為可以參考 init (重要,read it)。
- 建立 /etc/inittab,/init 預設會先分析此 script
::sysinit:/etc/init.d/rcS
::respawn:/sbin/getty -L 38400 tty1
::respawn:/sbin/getty -L 38400 tty2
::respawn:/sbin/getty -L 38400 tty3
::respawn:/sbin/getty -L 38400 tty4
::respawn:/sbin/getty -L ttyAMA0 115200 xterm
- 由 /etc/inittab 所指定 (或 /etc/inittab 不存在時,init 的預設行為),會去執行 /etc/init.d/rcS。
- 其執行的內容為
- 掛載 virtual file system,參考Magic Linux开发入门指南(五),基本說明的蠻清楚的。
- mdev: 初始 device node 及自動更新,參考 busybox 附帶的文檔 busybox-1.11.2/docs/mdev.txt
- 其除為網路設定部份,這就先不處理了。
-
#! /bin/sh
mkdir -p /proc
mount -t proc proc /proc
mkdir -p /sys
mount -t sysfs sysfs /sys
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
hostname qemu
ifconfig lo 127.0.0.1 up
# This board doesn't have a hardware clock, so system time is way off.
# The bugsybox dhcp client doesn't work when the clock is wrong.
# Oh well.
ifconfig eth0 10.0.2.15 up
rdate 10.0.2.2
ip route add default via 10.0.2.2
- 其執行的內容為
- inittab 其餘的部份為本機端終端機啟動的個數,參考 Util-linux (getty 和login) 及 man getty。
- 允許登錄系統(log in)和得到命令行提示符(bash prompt)。
- 准備一個密碼文件/etc/passwd.login 登錄程序正是通過查詢該文件來確認您是否允許登錄的。我們可以只設置根系統用戶就夠了,而且不需要任何密碼!! 只需要在目標系統的密碼文件/etc/passwd加上此行 "root::0:0:root:/root:/bin/bash"即可。(/etc/group 也要加入 "root:x:0:")
- /etc/issue: 在終端機介面登入的時,顯示提示的字串。(如果想要讓使用者登入後取得一些訊息,可以寫在 /etc/motd)
- /etc/nsswitch.conf: name-server switch,用來控制名稱資訊轉換,例如,當系統要取得 password、group、host 等資訊時,會參考這個檔案以決定要從哪裡得到資訊。參考 man nsswitch.conf。
# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.
passwd: compat
group: compat
shadow: compat
hosts: files dns
networks: files
protocols: db files
services: db files
ethers: db files
rpc: db files
netgroup: nis - /etc/resolv.con: 參考簡介,man resolv.conf
nameserver 10.0.2.3
No comments:
Post a Comment