1. 解压 ubuntu-18.04.1-desktop-amd64.iso
2. 查看 boot/grub/grub.cfg,知道引导文件系统是 /casper/initrd.lz
menuentry "Try Ubuntu without installing" {
set gfxpayload=keep
linux /casper/vmlinuz file=/cdrom/preseed/ubuntu.seed boot=casper quiet splash ---
initrd /casper/initrd.lz
}
3. 解压 /casper/initrd.lz 到initrd目录,结构如下
4. 首先查看 init脚本文件,kernel将在启动后首先默认执行它,除非启动参数另外指定。
4.1 建立基本系统设备目录以支持应用程序运行,其中提前从启动参数提取quiet全局变量是因为它可能会被udev脚本引用。
export PATH=/sbin:/usr/sbin:/bin:/usr/bin
[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir -m 0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
mkdir -p /var/lock
mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
mount -t proc -o nodev,noexec,nosuid proc /proccase " $(cat /proc/cmdline) " in
*\ quiet\ *)
quiet=y
;;
*)
quiet=n
echo "Loading, please wait..."
;;
esac
export quiet# Note that this only becomes /dev on the real filesystem if udev's scripts
# are used; which they will be, but it's worth pointing out
mount -t devtmpfs -o nosuid,mode=0755 udev /dev
mkdir /dev/pts
mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true
mount -t tmpfs -o "noexec,nosuid,size=10%,mode=0755" tmpfs /run
mkdir -m 0755 /run/initramfs
导出全局变量 DPKG_ARCH
# Export the dpkg architecture
export DPKG_ARCH=. /conf/arch.conf
/conf/arch.conf内容很简单
DPKG_ARCH=amd64
导出有关变量,之后会在解析启动参数时对设定项进行赋值,init脚本运行结束时,这些变量大都会被用unset命令释放掉,避免增加无谓的系统负担,这一点值得学习。
# Export relevant variables
export ROOT=
export ROOTDELAY=
export ROOTFLAGS=
export ROOTFSTYPE=
export IP=
export IP6=
export BOOT=
export BOOTIF=
export UBIMTD=
export break=
export init=/sbin/init
export readonly=y
export rootmnt=/root
export debug=
export panic=
export blacklist=
export resume=
export resume_offset=
export drop_caps=
export fastboot=n
export forcefsck=n
export fsckfix=
export recovery=
设置hostname,要定制的话修改 etc/hostname的值,默认似乎没有这个文件。
# mdadm needs hostname to be set. This has to be done before the udev rules are called!
if [ -f "/etc/hostname" ]; then
/bin/hostname -F /etc/hostname >/dev/null 2>&1
fi
导出各种需要的外部变量(*.conf)和函数定义(/scripts/functions)。后面用的比较多的是maybe_break() 和run_scripts()
# Bring in the main config
. /conf/initramfs.conf
for conf in conf/conf.d/*; do
[ -f ${conf} ] && . ${conf}
done
. /scripts/functions
之后是解析启动参数 /proc/cmdline,比较常用的有init=,root=,boot=
init=*)
init=${x#init=}
;;
root=*)
ROOT=${x#root=}
if [ -z "${BOOT}" ] && [ "$ROOT" = "/dev/nfs" ]; then
BOOT=nfs
fi
;;boot=*)
BOOT=${x#boot=}
;;
如果没有指定boot,将会设置默认值local,为什么不在之前定义时直接设置呢?恐怕是担心送的参数就是空的情况(boot= )
# Default to BOOT=local if no boot script defined.
if [ -z "${BOOT}" ]; then
BOOT=local
fi
之后是系统恢复变量的设置,暂时没有关注,童鞋自己分析吧。
if [ -n "${noresume}" ] || [ "$RESUME" = none ]; then
export noresume=y
unset resume
else
resume=${RESUME:-}
fi
之后是很重要的初始化脚本调用过程,将在“ubuntu-18.04.1-desktop-amd64.iso initrd 基本文件系统中启动脚本分析 (2)”中详述。以下是简略的初始化脚本或函数调用过程
/scripts/init-top
load_modules
/scripts/init-premount
. /scripts/local
. /scripts/nfs
. /scripts/${BOOT}
parse_numeric ${ROOT}
mount_top
mount_premount
mountroot
mount_bottom
nfs_bottom
local_bottom
/scripts/init-bottom