OS代码示例
Multiboot规范里提供了一个例程,演示了如何编写支持Multiboot引导的操作系统。官方的示例代码包含:
- multiboot2.h:Multiboot2规范头文件;
- boot.S:用于引导内核,同时包含Multiboot2标准头部的定义;
- kernel.c:最小内核程序。
为了编译上面的程序,编写Makefile如下:
CC = cc
LD = ld
CFLAGS = -m32 -fno-stack-protector
LDFLAGS = -Ttext 0x100000 -melf_i386 -nostdlib -nostartfiles
KERNEL_NAME = kernel
all: $(KERNEL_NAME)
$(KERNEL_NAME): boot.o kernel.o
$(LD) $(LDFLAGS) $^ -o kernel
boot.o: boot.S
$(CC) -c $(CFLAGS) $< -o $@
kernel.o: kernel.c
$(CC) -c $(CFLAGS) $< -o $@
clean:
rm -f *.o kernel
执行make,最终编译出ELF格式的最小内核程序:kernel
。接下来,我们将这个内核烧录到启动盘并使用虚拟机运行。
创建启动磁盘
- 使用dd创建磁盘镜像:
dd if=/dev/zero of=hd.img bs=512 count=131072
上面的命令创建了一个64MB大小的空白磁盘镜像文件。
- 使用
parted
在磁盘上创建引导分区
parted hd.img 'mklabel msdos mkpart primary fat16 1MB -1 set 1 boot on'
执行完后,查看磁盘信息:
3. 使用losetup
将磁盘镜像文件虚拟成块设备:
losetup --show -P -f hd.img
命令执行结果如下:
可以看到,系统为我们生成了一个新的loop设备/dev/loop0
,并且还有一个分区设备/dev/loop0p1
。
- 格式化文件系统并挂载到指定目录:
sudo mkfs.msdos /dev/loop0p1
sudo mount /dev/loop0p1 /mnt/loop0p1
- 拷贝内核程序到启动磁盘中:
sudo cp kernel /mnt/loop0p1
sync
- 安装grub引导程序,并配置引导选项:
sudo grub2-install --boot-directory=/mnt/loop0p1 --target=i386-pc /dev/loop0
echo "echo \"multiboot (hd0,msdos1)/kernel\nboot\" > /mnt/loop0p1/grub2/grub.cfg"
sync
至此,一个支持multiboot引导的启动盘制作完成,后面可以使用虚拟机来加载启动盘运行。
- 使用qemu加载启动盘运行:
qemu-system-x86_64 -drive format=raw,file=hd.img
相关参考
- Multiboot规范文档:https://www.gnu.org/savannah-checkouts/gnu/grub/manual/multiboot2/multiboot.html