参考陈香兰老师Linux源码分析的课件,编译完linux源码之后,准备制作一个文件系统。

本文介绍了两种文件系统的生成方式,包括:
    1. 自己制作init和/dev/ram和/dev/console(遇到了文件系统的错误,花了很长时间才解决)
    2. 利用busybox生成文件系统。

0x01首先创建一个应用程序

这个程序作为init程序,是linux启动后准备执行的程序。

#include <stdio.h>
#include <unistd.h>

void main(){
    while(1){
        printf("Hello!\n");
        sleep(1);
    }
}

静态编译:gcc test.c --static -o init (没有lib,必须静态编译)

0x02 建立文件系统 镜像

dd if=/dev/zero of=myinitrd4M.img bs=4096 count=1024
mke2fs myinitrd4M.img
mkdir rootfs
sudo mount -o loop myinitrd4M.img rootfs

将init拷贝到目标根目录下(linux启动后期会在根目录中寻找一个应用程序来运行,在根目录下提供init是一种可选方案)

sudo cp init rootfs/

准备dev目录

sudo mkdir rootfs/dev
#linux启动过程中会启用console设备
sudo mknod rootfs/dev/console c 5 1
#另外需要提供一个linux根设备,我们使用ram
sudo mknod rootfs/dev/ram b 1 0
sudo umount rootfs

至此,一个包含简单应用程序的根目录映像myinitrd4M.img就准备好了。

0x03 qemu启动

qemu-system-x86_64  -kernel ./linux-2.6.32.1/arch/x86/boot/bzImage -initrd ./testimg/myinitrd4M.img  -append "root=/dev/ram init=/init"

报错:

No filesystem could mount root, tried: ext3 vfat msdos iso9660

kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0 )

qemu缓存和主机缓存 qemu 文件系统_文件系统

搜索了很久很久之后,终于意识到这个问题本质是,qemu启动镜像的时候尝试了ext3 vfat msdos iso9660这些文件格式,却没有尝试ext2。查看一下我们之前创建的镜像文件格式:

qemu缓存和主机缓存 qemu 文件系统_qemu缓存和主机缓存_02

解决办法一:在rootfs中使用cpio生成新的镜像文件 

find . | cpio -o --format=newc > ../initrd.img
# 重新运行
qemu-system-x86_64  -kernel ./linux-2.6.32.1/arch/x86/boot/bzImage -initrd  testimg/initrd.img  -append "root=/dev/ram init=/init"

qemu缓存和主机缓存 qemu 文件系统_根目录_03

退出qemu : ctrl+a x

解决办法二(推荐):既然qemu使用了ext3,那么创建img时创建ext3不就可以了吗。

# 重新生成ext3格式的img文件,确保这时rootfs已经unmount了
dd if=/dev/zero of=myinitrd4M.img bs=4096 count=1024
mkfs.ext3 myinitrd4M.img

qemu缓存和主机缓存 qemu 文件系统_Kernel_04

 

mkdir rootfs
sudo mount -o loop myinitrd4M.img rootfs
sudo cp init rootfs/
sudo mkdir rootfs/dev
sudo mknod rootfs/dev/console c 5 1
sudo mknod rootfs/dev/ram b 1 0
sudo umount rootfs

启动qemu:

qemu-system-x86_64  -kernel ./linux-2.6.32.1/arch/x86/boot/bzImage -initrd  testimg/myinitrd4M.img  -append "root=/dev/ram init=/init"

qemu缓存和主机缓存 qemu 文件系统_根目录_05

 

0x04 利用busybox生成文件系统

上面是在文件系统中放入了init文件个/dev 设备文件,如果需要用busybox创建文件系统,下面从busybox中创建文件系统的方法,第一种最简洁但是换了内核之后会遇到一些问题,第二种比较稳定。

方法一:

 

参考下面简陋的bash脚本。把busybox中默认install生成的文件安装到rootfs,并创建/dev/console和/dev/ram即可。
条件:运行目录下有编译好的linux-2.6.32.1/arch/x86/boot/bzImage和busybox-1.28.4/_install,如果没有需要从源码重新编译。

参考

#!/bin/bash
# 1 create myinitrd40M.img
mkdir testimg
cd testimg
dd if=/dev/zero of=myinitrd40M.img bs=40960 count=1024
mkfs.ext3  myinitrd40M.img                                # 文件格式按需修改
# 2 mount myinitrd40M.img to rootfs  folder
mkdir rootfs
sudo mount -o loop myinitrd40M.img  rootfs
# 3 install busybox to rootfs
cd ../busybox-1.28.4
sudo make  CONFIG_PREFIX=../testimg/rootfs install
# 4 rootfs mknod and create initrd.img
cd ../testimg/rootfs
sudo rm -rf lost+found
sudo mkdir dev
sudo mknod dev/console c 5 1
sudo mknod dev/ram b 1 0  
# find . | cpio -o --format=newc > ../myinitrd40M.img   #已经是ext3文件格式,不需要再生成了
sleep 1
# 5 umount 
cd ../
sudo umount rootfs
cd ../
# 6 start qemu
qemu-system-x86_64 -kernel ./linux-2.6.32.1/arch/x86/boot/bzImage  -initrd  testimg/myinitrd40M.img    -append "console=ttyS0 ramdisk_size=409600 root=/dev/ram init=/bin/sh rw" -nographic

方法二:(推荐用这个)

利用busybox创建文件系统参考 https://www.anquanke.com/post/id/85837 里面介的两种方式来创建,测试可以成功。

方案一:

$ cd _install
$ mkdir -pv {bin,sbin,etc,proc,sys,usr/{bin,sbin}}
$ cat init
#!/bin/sh
echo "INIT SCRIPT"
mount -t proc none /proc
mount -t sysfs none /sys
mount -t debugfs none /sys/kernel/debug
mkdir /tmp
mount -t tmpfs none /tmp
mdev -s # We need this to find /dev/sda later
echo -e "nBoot took $(cut -d' ' -f1 /proc/uptime) secondsn"
exec /bin/sh
$ chmod +x init
$ find . -print0 | cpio --null -ov --format=newc  | gzip -9 > /tmp/initramfs-busybox-x86.cpio.gz

方案二:

#在install目录中添加inittab文件:
$ cat etc/inittab 
::sysinit:/etc/init.d/rcS
::askfirst:/bin/ash
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
::restart:/sbin/init
添加rcS文件
$ cat etc/init.d/rcS 
#!/bin/sh
#!/bin/sh
mount -t proc none /proc
mount -t sys none /sys
/bin/mount -n -t sysfs none /sys
/bin/mount -t ramfs none /dev
/sbin/mdev -
$ chmod +x ./etc/init.d/rcS
配置下dev目录
mkdir dev
sudo mknod dev/ttyAMA0 c 204 64
sudo mknod dev/null c 1 3
sudo mknod dev/console c 5 1
$ find . | cpio -o --format=newc > ../rootfs.img

每次修改了busybox下的文件后,执行find . | cpio -o --format=newc > ../rootfs.img重新创建img即可。

PS: 遇到一个小问题,暂时没解决,记录一下。编译linux源码的时候,用的是make defconfig,看了.config配置是x64位的。可是镜像确是在x86目录下创建的,file看了一下是x86镜像,可是qemu起的时候却说需要用64位来启动,很奇怪。希望路过的同学指教....

qemu缓存和主机缓存 qemu 文件系统_linux_06

qemu缓存和主机缓存 qemu 文件系统_根目录_07