BLFS文件系统
initramfs
initramfs
的唯一用途是挂载根文件系统:
initramfs是在普通根文件系统上可以找到的一套完整目录
initramfs被捆绑到单个
cpio
归档中,并使用几种压缩算法之一进行压缩
在系统启动时,引导加载程序将内核和 initramfs
映像加载到内存中并启动黑河。内核检查 initramfs
是否存在,如果找到,就将其挂载为 /
并运行 /init
。 init
通常是一个shell脚本。
注意,如果使用 initramfs
,启动过程将花费更长时间,甚至可能长很多。
构建initramfs
以下脚本是一个基本 initramfs
,允许通过 分区UUID
或 分区LABEL
或 LVM逻辑卷的一个rootfs 来指定 rootfs
。该脚本不支持加密root文件系统或者从网卡挂载rootfs。如果需要更完整能力,则参考 the LFS Hints 或者 Dracut
安装以下脚本:
mkinitramfs
脚本cat > /usr/sbin/mkinitramfs << "EOF"
#!/bin/bash
# This file based in part on the mkinitramfs script for the LFS LiveCD
# written by Alexander E. Patrakov and Jeremy Huntwork.
copy()
{
local file
if [ "$2" = "lib" ]; then
file=$(PATH=/usr/lib type -p $1)
else
file=$(type -p $1)
fi
if [ -n "$file" ] ; then
cp $file $WDIR/usr/$2
else
echo "Missing required file: $1 for directory $2"
rm -rf $WDIR
exit 1
fi
}
if [ -z $1 ] ; then
INITRAMFS_FILE=initrd.img-no-kmods
else
KERNEL_VERSION=$1
INITRAMFS_FILE=initrd.img-$KERNEL_VERSION
fi
if [ -n "$KERNEL_VERSION" ] && [ ! -d "/usr/lib/modules/$1" ] ; then
echo "No modules directory named $1"
exit 1
fi
printf "Creating $INITRAMFS_FILE... "
binfiles="sh cat cp dd killall ls mkdir mknod mount "
binfiles="$binfiles umount sed sleep ln rm uname"
binfiles="$binfiles readlink basename"
# Systemd installs udevadm in /bin. Other udev implementations have it in /sbin
if [ -x /usr/bin/udevadm ] ; then binfiles="$binfiles udevadm"; fi
sbinfiles="modprobe blkid switch_root"
# Optional files and locations
for f in mdadm mdmon udevd udevadm; do
if [ -x /usr/sbin/$f ] ; then sbinfiles="$sbinfiles $f"; fi
done
# Add lvm if present (cannot be done with the others because it
# also needs dmsetup
if [ -x /usr/sbin/lvm ] ; then sbinfiles="$sbinfiles lvm dmsetup"; fi
unsorted=$(mktemp /tmp/unsorted.XXXXXXXXXX)
DATADIR=/usr/share/mkinitramfs
INITIN=init.in
# Create a temporary working directory
WDIR=$(mktemp -d /tmp/initrd-work.XXXXXXXXXX)
# Create base directory structure
mkdir -p $WDIR/{dev,run,sys,proc,usr/{bin,lib/{firmware,modules},sbin}}
mkdir -p $WDIR/etc/{modprobe.d,udev/rules.d}
touch $WDIR/etc/modprobe.d/modprobe.conf
ln -s usr/bin $WDIR/bin
ln -s usr/lib $WDIR/lib
ln -s usr/sbin $WDIR/sbin
ln -s lib $WDIR/lib64
# Create necessary device nodes
mknod -m 640 $WDIR/dev/console c 5 1
mknod -m 664 $WDIR/dev/null c 1 3
# Install the udev configuration files
if [ -f /etc/udev/udev.conf ]; then
cp /etc/udev/udev.conf $WDIR/etc/udev/udev.conf
fi
for file in $(find /etc/udev/rules.d/ -type f) ; do
cp $file $WDIR/etc/udev/rules.d
done
# Install any firmware present
cp -a /usr/lib/firmware $WDIR/usr/lib
# Copy the RAID configuration file if present
if [ -f /etc/mdadm.conf ] ; then
cp /etc/mdadm.conf $WDIR/etc
fi
# Install the init file
install -m0755 $DATADIR/$INITIN $WDIR/init
if [ -n "$KERNEL_VERSION" ] ; then
if [ -x /usr/bin/kmod ] ; then
binfiles="$binfiles kmod"
else
binfiles="$binfiles lsmod"
sbinfiles="$sbinfiles insmod"
fi
fi
# Install basic binaries
for f in $binfiles ; do
ldd /usr/bin/$f | sed "s/\t//" | cut -d " " -f1 >> $unsorted
copy /usr/bin/$f bin
done
for f in $sbinfiles ; do
ldd /usr/sbin/$f | sed "s/\t//" | cut -d " " -f1 >> $unsorted
copy $f sbin
done
# Add udevd libraries if not in /usr/sbin
if [ -x /usr/lib/udev/udevd ] ; then
ldd /usr/lib/udev/udevd | sed "s/\t//" | cut -d " " -f1 >> $unsorted
elif [ -x /usr/lib/systemd/systemd-udevd ] ; then
ldd /usr/lib/systemd/systemd-udevd | sed "s/\t//" | cut -d " " -f1 >> $unsorted
fi
# Add module symlinks if appropriate
if [ -n "$KERNEL_VERSION" ] && [ -x /usr/bin/kmod ] ; then
ln -s kmod $WDIR/usr/bin/lsmod
ln -s kmod $WDIR/usr/bin/insmod
fi
# Add lvm symlinks if appropriate
# Also copy the lvm.conf file
if [ -x /usr/sbin/lvm ] ; then
ln -s lvm $WDIR/usr/sbin/lvchange
ln -s lvm $WDIR/usr/sbin/lvrename
ln -s lvm $WDIR/usr/sbin/lvextend
ln -s lvm $WDIR/usr/sbin/lvcreate
ln -s lvm $WDIR/usr/sbin/lvdisplay
ln -s lvm $WDIR/usr/sbin/lvscan
ln -s lvm $WDIR/usr/sbin/pvchange
ln -s lvm $WDIR/usr/sbin/pvck
ln -s lvm $WDIR/usr/sbin/pvcreate
ln -s lvm $WDIR/usr/sbin/pvdisplay
ln -s lvm $WDIR/usr/sbin/pvscan
ln -s lvm $WDIR/usr/sbin/vgchange
ln -s lvm $WDIR/usr/sbin/vgcreate
ln -s lvm $WDIR/usr/sbin/vgscan
ln -s lvm $WDIR/usr/sbin/vgrename
ln -s lvm $WDIR/usr/sbin/vgck
# Conf file(s)
cp -a /etc/lvm $WDIR/etc
fi
# Install libraries
sort $unsorted | uniq | while read library ; do
# linux-vdso and linux-gate are pseudo libraries and do not correspond to a file
# libsystemd-shared is in /lib/systemd, so it is not found by copy, and
# it is copied below anyway
if [[ "$library" == linux-vdso.so.1 ]] ||
[[ "$library" == linux-gate.so.1 ]] ||
[[ "$library" == libsystemd-shared* ]]; then
continue
fi
copy $library lib
done
if [ -d /usr/lib/udev ]; then
cp -a /usr/lib/udev $WDIR/usr/lib
fi
if [ -d /usr/lib/systemd ]; then
cp -a /usr/lib/systemd $WDIR/usr/lib
fi
if [ -d /usr/lib/elogind ]; then
cp -a /usr/lib/elogind $WDIR/usr/lib
fi
# Install the kernel modules if requested
if [ -n "$KERNEL_VERSION" ]; then
find \
/usr/lib/modules/$KERNEL_VERSION/kernel/{crypto,fs,lib} \
/usr/lib/modules/$KERNEL_VERSION/kernel/drivers/{block,ata,nvme,md,firewire} \
/usr/lib/modules/$KERNEL_VERSION/kernel/drivers/{scsi,message,pcmcia,virtio} \
/usr/lib/modules/$KERNEL_VERSION/kernel/drivers/usb/{host,storage} \
-type f 2> /dev/null | cpio --make-directories -p --quiet $WDIR
cp /usr/lib/modules/$KERNEL_VERSION/modules.{builtin,order} \
$WDIR/usr/lib/modules/$KERNEL_VERSION
if [ -f /usr/lib/modules/$KERNEL_VERSION/modules.builtin.modinfo ]; then
cp /usr/lib/modules/$KERNEL_VERSION/modules.builtin.modinfo \
$WDIR/usr/lib/modules/$KERNEL_VERSION
fi
depmod -b $WDIR $KERNEL_VERSION
fi
( cd $WDIR ; find . | cpio -o -H newc --quiet | gzip -9 ) > $INITRAMFS_FILE
# Prepare early loading of microcode if available
if ls /usr/lib/firmware/intel-ucode/* >/dev/null 2>&1 ||
ls /usr/lib/firmware/amd-ucode/* >/dev/null 2>&1; then
# first empty WDIR to reuse it
rm -r $WDIR/*
DSTDIR=$WDIR/kernel/x86/microcode
mkdir -p $DSTDIR
if [ -d /usr/lib/firmware/amd-ucode ]; then
cat /usr/lib/firmware/amd-ucode/microcode_amd*.bin > $DSTDIR/AuthenticAMD.bin
fi
if [ -d /usr/lib/firmware/intel-ucode ]; then
cat /usr/lib/firmware/intel-ucode/* > $DSTDIR/GenuineIntel.bin
fi
( cd $WDIR; find . | cpio -o -H newc --quiet ) > microcode.img
cat microcode.img $INITRAMFS_FILE > tmpfile
mv tmpfile $INITRAMFS_FILE
rm microcode.img
fi
# Remove the temporary directories and files
rm -rf $WDIR $unsorted
printf "done.\n"
EOF
chmod 0755 /usr/sbin/mkinitramfs
init.in
脚本mkdir -p /usr/share/mkinitramfs &&
cat > /usr/share/mkinitramfs/init.in << "EOF"
#!/bin/sh
PATH=/usr/bin:/usr/sbin
export PATH
problem()
{
printf "Encountered a problem!\n\nDropping you to a shell.\n\n"
sh
}
no_device()
{
printf "The device %s, which is supposed to contain the\n" $1
printf "root file system, does not exist.\n"
printf "Please fix this problem and exit this shell.\n\n"
}
no_mount()
{
printf "Could not mount device %s\n" $1
printf "Sleeping forever. Please reboot and fix the kernel command line.\n\n"
printf "Maybe the device is formatted with an unsupported file system?\n\n"
printf "Or maybe filesystem type autodetection went wrong, in which case\n"
printf "you should add the rootfstype=... parameter to the kernel command line.\n\n"
printf "Available partitions:\n"
}
do_mount_root()
{
mkdir /.root
[ -n "$rootflags" ] && rootflags="$rootflags,"
rootflags="$rootflags$ro"
case "$root" in
/dev/* ) device=$root ;;
UUID=* ) eval $root; device="/dev/disk/by-uuid/$UUID" ;;
PARTUUID=*) eval $root; device="/dev/disk/by-partuuid/$PARTUUID" ;;
LABEL=* ) eval $root; device="/dev/disk/by-label/$LABEL" ;;
"" ) echo "No root device specified." ; problem ;;
esac
while [ ! -b "$device" ] ; do
no_device $device
problem
done
if ! mount -n -t "$rootfstype" -o "$rootflags" "$device" /.root ; then
no_mount $device
cat /proc/partitions
while true ; do sleep 10000 ; done
else
echo "Successfully mounted device $root"
fi
}
do_try_resume()
{
case "$resume" in
UUID=* ) eval $resume; resume="/dev/disk/by-uuid/$UUID" ;;
LABEL=*) eval $resume; resume="/dev/disk/by-label/$LABEL" ;;
esac
if $noresume || ! [ -b "$resume" ]; then return; fi
ls -lH "$resume" | ( read x x x x maj min x
echo -n ${maj%,}:$min > /sys/power/resume )
}
init=/sbin/init
root=
rootdelay=
rootfstype=auto
ro="ro"
rootflags=
device=
resume=
noresume=false
mount -n -t devtmpfs devtmpfs /dev
mount -n -t proc proc /proc
mount -n -t sysfs sysfs /sys
mount -n -t tmpfs tmpfs /run
read -r cmdline < /proc/cmdline
for param in $cmdline ; do
case $param in
init=* ) init=${param#init=} ;;
root=* ) root=${param#root=} ;;
rootdelay=* ) rootdelay=${param#rootdelay=} ;;
rootfstype=*) rootfstype=${param#rootfstype=} ;;
rootflags=* ) rootflags=${param#rootflags=} ;;
resume=* ) resume=${param#resume=} ;;
noresume ) noresume=true ;;
ro ) ro="ro" ;;
rw ) ro="rw" ;;
esac
done
# udevd location depends on version
if [ -x /sbin/udevd ]; then
UDEVD=/sbin/udevd
elif [ -x /lib/udev/udevd ]; then
UDEVD=/lib/udev/udevd
elif [ -x /lib/systemd/systemd-udevd ]; then
UDEVD=/lib/systemd/systemd-udevd
else
echo "Cannot find udevd nor systemd-udevd"
problem
fi
${UDEVD} --daemon --resolve-names=never
udevadm trigger
udevadm settle
if [ -f /etc/mdadm.conf ] ; then mdadm -As ; fi
if [ -x /sbin/vgchange ] ; then /sbin/vgchange -a y > /dev/null ; fi
if [ -n "$rootdelay" ] ; then sleep "$rootdelay" ; fi
do_try_resume # This function will not return if resuming from disk
do_mount_root
killall -w ${UDEVD##*/}
exec switch_root /.root "$init" "$@"
EOF
使用initramfs
在使用
initramfs
之前必须完成 cpio如果系统分区使用了 LVM 或 mdadm ,则必须先安装这两个工具才能执行
initramfs
(目前我没有)生成
initramfs
运行命令
6.10.5
内核的 initramfsmkinitramfs 6.10.5
这里参数 6.10.5
是可选的,也就是 /lib/modules
的一个子目录。如果没有modules指定,那么将生成名为 initrd.img-no-kmods
,如果指定内核版本,就会生成 initrd.img-$KERNEL_VERSION
用于特定内核。输出文件存放在当前目录。
6.10.5
内核的 initramfs 输出文件案例-bash-5.2# mkinitramfs 6.10.5
Creating initrd.img-6.10.5... done.
-bash-5.2# ls -lh
total 9.3M
-rw-r--r-- 1 root root 9.3M Jan 26 21:45 initrd.img-6.10.5
备注
如果已经在 CPU microcode 中已经将 intel-ucode
目录完整复制到 /lib/firmware
目录下,那么 mkinitramfs
会自动添加到 intrd
中(也就是不需要独立的 microcode.img
了。
不过, grub.cfg
中 initrd
可以加载多个 img
initrd /microcode.img /other-initrd.img
最后修订
/boot/grub/grub.cfg
添加一行:
menuentry "GNU/Linux, Linux 6.10.5-lfs-12.2" {
search --set=root --fs-uuid 81368941-bd96-4539-bf8e-7215d532a872
linux /boot/vmlinuz-6.10.5-lfs-12.2 root=PARTUUID=cf8d6f20-92bf-4f81-982e-50bea63e6ca3 ro
initrd /boot/initrd.img-6.10.5
}
警告
目前我实际还没有添加 initrd.img-6.10.5
配置行,因为目前还没有需要特别预先加载的内核模块和工具。
目前我还是只使用 CPU microcode 预先加载CPU微码
如果后续有需要我再添加 initramfs