一、创建空磁盘qemu-img create -f raw gf.os 100Mhexdump -C -n 512 gf.os #可以看到每个字节都是0也就是空白磁盘二、用空磁盘启动qemu-system-x86_64 -hda gf.os -nographic打印信息如下SeaBIOS (version 1.13.0-2.el8) iPXE (http://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM07F90A5007ED0A50 CA00 Booting from Hard Disk... Boot failed: not a bootable disk Booting from Floppy... Boot failed: could not read the boot disk Booting from DVD/CD... Boot failed: Could not read from CDROM (code 0003) Booting from ROM... iPXE (PCI 00:03.0) starting execution...ok iPXE initialising devices...ok iPXE 1.0.0 -- Open Source Network Boot Firmware -- http://ipxe.org Features: DNS HTTP iSCSI TFTP VLAN AoE ELF MBOOT PXE bzImage Menu PXEXT net0: 52:54:00:12:34:56 using 82540em on 0000:00:03.0 (open) [Link:up, TX:0 TXE:0 RX:0 RXE:0] Configuring (net0 52:54:00:12:34:56).............. ok net0: 10.0.2.15/255.255.255.0 gw 10.0.2.2 net0: fec0::5054:ff:fe12:3456/64 gw fe80::2 net0: fe80::5054:ff:fe12:3456/64 Nothing to boot: No such file or directory (http://ipxe.org/2d03e13b) No more network devices No bootable device.另起一个终端杀掉qemupkill -9 qemu-system三、对磁盘做一下分区。从前面的信息看默认走的是bios启动fdisk默认也是bios分区如果要创建gpt分区需要先敲m帮助看一下g是设置为gpt分区格式后面创建分区都是同样的命令n创建出来的结果也可以对比一下有一点差别。用n创建分区创建一个主分区即可,w保存并退出。hexdump -C -n 512 gf.os 可以查看fdisk到底写入了啥就是在0扇区写了分区信息以及0分区最后的魔数 55aa四、再次启动qemuqemu-system-x86_64 -hda gf.os -nographic打印信息如下SeaBIOS (version 1.13.0-2.el8) iPXE (http://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM07F90A5007ED0A50 CA00 Booting from Hard Disk...五、格式化文件系统安装grubsudo losetup -f --show gf.os # 输出为 /dev/loop0 sudo kpartx -av /dev/loop0 # 此时会生成 /dev/mapper/loop0p1 # 不用时可以通过下面的命令释放 # sudo kpartx -d /dev/loop0 # sudo losetup -d /dev/loop0 sudo mkdir -p /mnt/rootfs sudo mount /dev/mapper/loop0p1 /mnt/rootfs sudo mkfs.ext4 /dev/mapper/loop0p1 sudo grub2-install --targeti386-pc --root-directory/mnt/rootfs --boot-directory/mnt/rootfs/boot /dev/loop0 --此时grub 写了0扇区2~63扇区 还有文件系统中的grub2目录 /mnt/rootfs/boot/grub2 sudo umount /mnt/rootfs六、再次启动qemuqemu-system-x86_64 -hda gf.os -nographic打印信息如下SeaBIOS (version 1.13.0-2.el8) iPXE (http://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM07F90A5007ED0A50 CA00 Booting from Hard Disk... .. error: ../../grub-core/disk/i386/pc/biosdisk.c:546:failure reading sector 0x0 fr om fd0. error: ../../grub-core/kern/disk.c:237:disk lvmid/IQGNsA-CSsQ-2A7y-rNYy-VbQx-tj WB-S12NQ8/VYObIf-KSbT-k4Mi-gFY9-sPDE-3YE8-wjpdkY not found. Entering rescue mode... grub rescue grub rescue grub rescue七、拷贝本机内核编辑grub.cfgsudo mount /dev/mapper/loop0p1 /mnt/rootfs下面拷贝内核编辑grub.cfg sudo cp /boot/vmlinuz-4.19.112-2.el8.x86_64 /mnt/rootfs/boot/ sudo vi /mnt/rootfs/boot/grub2/grub.cfg menuentry My GF OS { set root(hd0,msdos1) linux /boot/vmlinuz-4.19.112-2.el8.x86_64 root/dev/sda1 rw consolettyS0 }syncsudo umount /mnt/rootfs八、再次启动qemuqemu-system-x86_64 -hda gf.os -nographic内核启动了打印信息如下缺少init[ 5.979636] —[ end Kernel panic - not syncing: No working init found.九、拷贝busyboxsudo mount /dev/mapper/loop0p1 /mnt/rootfs ls code/gitcode/busybox/gfos bin sbin usr cp -r code/gitcode/busybox/gfos/* /mnt/rootfs/ rm /mnt/rootfs/sbin/init #删除这个init程序后内核会把shell当做init sudo umount /mnt/rootfs十、再次启动qemuqemu-system-x86_64 -hda gf.os -nographic打印如下[ 5.401956] x86/mm: Checked WX mappings: passed, no WX pages found. [ 5.403218] rodata_test: all tests were successful [ 5.403786] Run /sbin/init as init process [ 5.407514] Run /etc/init as init process [ 5.408012] Run /bin/init as init process [ 5.411401] Run /bin/sh as init process /bin/sh: cant access tty; job control turned off ~ # ls bin boot lostfound sbin usr ~ # ps PID USER TIME COMMAND ps: cant open /proc: No such file or directory ~ # #ls命令可以使用ps命令不能使用 #手工创建 /proc文件夹然后挂载 mount -t proc none /proc #ls /proc 就可以看到进程信息了 ps 也可以看到进程了。top命令也可以用了。 ~ # mkdir /sys ~ # mount -t sysfs none /sys ~ # ls /sys block class devices fs kernel power bus dev firmware hypervisor module ~ # mkdir dev ~ # mount -t devtmpfs devtmpfs /dev ~ # ls /dev autofs tty22 tty7 bsg tty23 tty8 console tty24 tty9 cpu tty25 ttyS0 cpu_dma_latency tty26 ttyS1 full tty27 ttyS10 hpet tty28 ttyS11 hwrng tty29 ttyS12 input tty3 ttyS13 kmsg tty30 ttyS14 mapper tty31 ttyS15 mcelog tty32 ttyS16 md0 tty33 ttyS17 mem tty34 ttyS18 memory_bandwidth tty35 ttyS19 network_latency tty36 ttyS2 network_throughput tty37 ttyS20 null tty38 ttyS21 nvram tty39 ttyS22 port tty4 ttyS23 ptmx tty40 ttyS24 random tty41 ttyS25 raw tty42 ttyS26 rtc0 tty43 ttyS27 sda tty44 ttyS28 sda1 tty45 ttyS29 sg0 tty46 ttyS3 sg1 tty47 ttyS30 snapshot tty48 ttyS31 sr0 tty49 ttyS4 tty tty5 ttyS5 tty0 tty50 ttyS6 tty1 tty51 ttyS7 tty10 tty52 ttyS8 tty11 tty53 ttyS9 tty12 tty54 urandom tty13 tty55 usbmon0 tty14 tty56 vcs tty15 tty57 vcs1 tty16 tty58 vcsa tty17 tty59 vcsa1 tty18 tty6 vcsu tty19 tty60 vcsu1 tty2 tty61 vga_arbiter tty20 tty62 zero tty21 tty63 ~ # df Filesystem 1K-blocks Used Available Use% Mounted on /dev/root 94069 18027 68947 21% / devtmpfs 48644 0 48644 0% /dev十一、优化到上一步这个系统已经可以基本运行了。但是挂载的动作是手工做的init也是用sh代替的。下面启动真的initsudo mount /dev/mapper/loop0p1 /mnt/rootfs# 创建inittab在表中第一行配置要先启动/etc/init.d/rcS脚本 vi etc/inittab # 系统启动时最先执行一次阻塞后续动作 ::sysinit:/etc/init.d/rcS # 在控制台提供一个交互式 Shell崩溃或退出后自动重启 # 因为你用了 -nographic所以指定 ttyS0 作为控制台 #::respawn:/sbin/getty -L ttyS0 115200 vt100 ttyS0::respawn:/bin/sh # 按下 CtrlAltDel 时重启 ::ctrlaltdel:/sbin/reboot # 系统关机时执行的操作 ::shutdown:/bin/umount -a -r# 创建启动脚本 vi etc/init.d/rcS #!/bin/sh # 挂载虚拟文件系统让内核和用户空间能沟通 mount -t proc none /proc mount -t sysfs none /sys # 动态创建设备节点强烈建议加上这样就不需要手动 mknod 了 mount -t devtmpfs devtmpfs /dev # 设置主机名 hostname gf-os # 打印启动成功信息 echo GF-OS is up and running!最后要给这个脚本设置权限chmod x etc/init.d/rcSsudo umount /mnt/rootfs这次启动各项功能就正常了。ps、vi、reboot、poweroff 都可以使用十二、再优化支持登陆sudo mount /dev/mapper/loop0p1 /mnt/rootfs1、 inittab中改为首先启动getty这个命令会调用login,以及sh ::respawn:/sbin/getty -L ttyS0 115200 vt100 #ttyS0::respawn:/bin/sh 2、创建root用户的目录把root的密码设置为空 mkdir /mnt/rootfs/root 目录 echo root:x:0:root /mnt/rootfs/etc/group echo root:x:0:0:root:/root:/bin/sh/mnt/rootfs/etc/passwd echo root::20634:0:99999:7:::/mnt/rootfs/etc/shadow chmod 600 /etc/shadowsudo umount /mnt/rootfs然后启动qemu进入linux系统后就会提示输入登陆用户名和密码然后可以在linux中用passwd命令修改root密码。十三、网络下载linux内核使用默认配置默认也会编译这个网卡make defconfigDevice Drivers - Network device support - Ethernet driver support - Intel devices找到 Intel® PRO/1000 PCI-Express Gigabit Ethernet supportmake -j$(nproc)编译好的内核拷贝到磁盘镜像中sudo cp arch/x86/boot/bzImage /mnt/rootfs/boot/启动qemuqemu-system-x86_64 -hda gf.os -nographic -netdev user,idnet0 -device e1000,netdevnet0进去后可以看到三个网卡一个环回网卡一个eth0还有一个sit0但网卡都没有启动且无ip地址ip link set lo upip addr add 127.0.0.1/8 dev loip link set eth0 upip addr add 10.0.2.15/24 dev eth0ip route add default via 10.0.2.2 dev eth0然后就可以ping通127.0.0.1和10.0.2.15 另外网关10.0.2.2也可以ping通但宿主机10.137.239.107和其它机器还是ping不通提示宿主机理论上是不通的因为qemu默认是nat模式其它机器也不通就不知道原因了AI也没有分析出来