定制一个最小的linux 系统
一个操作系统宏观上分为两个部分,kernel和shell(核和壳),kernel就是操作系统内核,shell在kernel之上,提供与用户交互的界面,包括CLI(命令行界面)和GUI(图形用户界面)。除此之外还有基础运行库(如c库、posix)等基础软件。只有kernel,不能算作一个操作系统,因为什么也做不了。本文通过linux内核和busybox工具集,制作一个最简单的linux系统。
环境准备
安装必要的软件包
sudo apt update
sudo apt upgrade
sudo apt install build-essential git kconfig-frontends flex bison libelf-dev bc libssl-dev qemu qemu-system-x86
开始
编译 linux-kernel
建议直接从https://www.kernel.org/ 下载 tar -xvJf linux-5.15.175.tar.xz
官方这个这个拉下来大概5g多
git clone https:
#或者国内的镜像 git clone https:
git checkout
|
make ARCH=x86_64 defconfig
make menuconfig
make bzImage -j
如果卡死,可能是内存过小,可单线程编译
编译busybox
获取并编译busybox
git clone https:
git checkout 1_36_stable
make menuconfig
|
启用静态链接:Busybox Settings -> Build Options -> Build BusyBox as a static binary (no shared libs)
。
make -j$(nproc) make install
|
制作 initramfs
bin sbin usr dev etc init proc sys
cd busybox/_install rm linuxrc mkdir -p etc/init.d
# 下面这个如不复制,可以在init之前切换到用户态sysint时候创建 sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/
echo "::sysinit:/bin/sh" > etc/inittab
|
编辑 etc/init.d/init文件
#!/bin/busybox sh
export PATH=/sbin:/bin:/usr/sbin:/usr/bin
if [ "$$" -ne 1 ]; then echo "Error: This script can only be run as the init process (PID 1)." >&2 exit 1 fi
[ -d /proc ] || mkdir -p /proc [ -d /dev ] || mkdir -p /dev [ -d /sys ] || mkdir -p /sys [ -d /tmp ] || mkdir -p /tmp [ -d /var/run ] || mkdir -p /var/run [ -d /root ] || mkdir -p /root
mount -t proc proc /proc mount -t sysfs -o noexec,nosuid,nodev sysfs /sys
exec /sbin/init < /dev/console > /dev/console 2>&1
|
编辑etc/inittab文件
::sysinit:/etc/init.d/sysinit ::ctrlaltdel:/sbin/reboot ::shutdown:/sbin/poweroff ::restart:/sbin/init
tty1::respawn:/bin/sh tty2::respawn:/bin/sh ttyS0::respawn:/bin/sh
tty1::respawn:/sbin/getty 115200 tty1 tty2::respawn:/sbin/getty 115200 tty2 ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100
|
编辑 etc/init.d/sysinit
#!/bin/sh
echo "Tiny linux Starting sysinit..."
create_device_nodes() { echo "Creating essential device nodes..." mknod -m 666 /dev/null c 1 3 mknod -m 600 /dev/console c 5 1 mknod -m 666 /dev/tty c 5 0
for i in 0 1 2; do mknod -m 620 /dev/tty$i c 4 $i done
mknod -m 620 /dev/ttyS0 c 4 64 }
mount_filesystems() { echo "Mounting virtual filesystems..." mount -t devtmpfs devtmpfs /dev mount -t proc proc /proc mount -t sysfs sysfs /sys mount -t devpts devpts /dev/pts mount -t tmpfs tmpfs /dev/shm }
setup_mdev() { echo "Setting up mdev..." mdev -s }
create_standard_links() { echo "Creating standard stream links..." ln -snf /proc/self/fd /dev/fd ln -snf fd/0 /dev/stdin ln -snf fd/1 /dev/stdout ln -snf fd/2 /dev/stderr [ -e /proc/kcore ] && ln -snf /proc/kcore /dev/core }
load_sysctl() { if [ -e /etc/sysctl.conf ]; then echo "Loading sysctl settings..." sysctl -p /etc/sysctl.conf fi }
start_acpid() { if [ -e /proc/acpi ]; then echo "Starting acpid..." acpid &>/dev/null fi }
main() { create_device_nodes mount_filesystems setup_mdev create_standard_links load_sysctl start_acpid echo "Sysinit completed." }
main
|
可选,配置用户权限,设置用户账号密码
#!/bin/sh
echo "root:x:0:0:root:/root:/bin/sh" > etc/passwd
echo "root:$(openssl passwd -6 root):0:0:99999:7:::" > etc/shadow
chmod 644 etc/passwd && chmod 600 etc/shadow
|
最后的一些权限准备
sudo chmod +x etc/init.d/init sudo chmod +x etc/init.d/sysinit
cd .. sudo chown -R root:root _install/
|
生成最终需要的 initramfs.cpio.gz
find . | cpio -o --format=newc | gzip > ../initramfs.cpio.gz
|
准备磁盘和grub
dd if=/dev/zero of=tiny-linux.img bs=1M count=32
sudo losetup -Pf --show tiny-linux.img fdisk /dev/loopX n p w sync
sudo mkfs.ext4 /dev/loopXp1
mkdir -p tmpimg sudo mount /dev/loopXp1 tmpimg/
sudo cp linux-5.15.175/arch/x86_64/boot/bzImage tmpimg/ sudo cp busybox/initramfs.cpio.gz tmpimg/
sudo grub-install --boot-directory=tmpimg/boot/ --target=i386-pc --modules=part_msdos tiny-linux.img
|
编辑grub2 配置 tmpimg/boot/grub/grub.cfg
set default=0 set timeout=5
menuentry 'CA Tiny Linux' { linux /bzImage console=tty0 console=ttyS0,115200 initrd /initramfs.cpio.gz }
|
运行
qemu-system-x86_64 -hda tiny-linux.img -nographic -nographic 没有图形界面时候使用,可以在终端显示
qemu-img convert -f raw -O vmdk tiny-linux.img tiny-linux.img.vmdk
|