操作系统实战45讲--最全HellOS实验指南
此篇专栏详细记录《极客时间-操作系统实战45讲》的第一个实验HelloOS的实验的全部过程。
笔者同时用虚拟机和物理机完成了实验,基本将所有可能到的坑都踩了一遍,在此详细记录下所有的实验步骤与要点供大家参考。
大家跟着每一步实现,保证一定能够将实验完成。先贴一张实验成功图。

专栏课程链接:https://time.geekbang.org/column/intro/411

一、初始环境配置
1.一个配置好的Linux系统,笔者使用的是 Ubuntu 20.04.2.0 LTS,虚拟机使用的是Oracle VM
VirtualBox。在物理机上安装了双系统(Windows、Ubuntu),同时也使用虚拟机在Windows上安装了Ubuntu。
对比在物理机和在虚拟机上完成实验的两种方式,我这里推荐在虚拟机上完成,可以少踩很多的坑。虚拟机上的实验步骤基本和老师在文章中写的一样,而在物理机上就有很多出入,有很多地方因为个体电脑差异,需要进行一些修改,接下来对这两种方式我都会进行讲解。
具体虚拟机安装与配置的问题,请大家参考网上的资料完成,我就不在这里进行赘述。以下我附上个人在配置时参考的一篇文章。
http://www.1zlab.com/wiki/python-opencv-tutorial/virtualbox-ubuntu-vm-install/
2.安装nasm
sudo apt-get install nasm
3.安装gcc,以下这个命令会一次性安装包括gcc在内的一系列编译软件
sudo apt install build-essential
以上nasm和gcc的安装都是为之后make完成编译和链接工作做准备
二、文件准备
1.将老师放在gitee上的代码拷贝下来,网页链接如下
https://gitee.com/lmos/cosmos/tree/master/lesson02/HelloOS
2.打开terminal,使用"cd"命令进入拷贝下来的文件夹(或者我一般是进入对应文件夹后右键打开terminal),运行以下命令完成编译链接得到HelloOS.bin
make -f Makefile
3.将生成的HelloOS.bin文件拷贝到/boot文件夹下。
其实不是一定强制要HellOS.bin放在/boot文件夹下才能够完成启动,这只是遵循惯例而已。将HellOS放在其他文件夹下,然后之后在grub.cfg文件中设置相应的HellOS.bin的地址即可。
拷贝可以使用"mv"命令,我以自己的情况举例。在HelloOS.bin所在的文件夹打开terminal,使用以下命令进行文件移动
sudo mv HelloOS.bin /boot
4. 修改/etc/default/grub文件,将GRUB_TIMEOUT修改为30,设置进入默认启动项的等候时间,默认值为10秒,我们将其延长。使用一下命令打开并编辑grub文件
sudo gedit /etc/default/grub

编辑完成后,使用以下命令更新文件设置
sudo update-grub
tips:sudo update-grub会将/boot/grub/grub.cfg文件给初始化,如果之前已经添加过menuentry的同学需要重新添加。
menuentry 'HelloOS' {
.................
}
5. 在/boot/grub/grub.cfg中添加menuentry,这一步有非常多的坑,老师在文章中的讲解比较简单,但是在具体实现的时候有很多细节要注意。首先打开grub.cfg这个文件,使用以下命令
sudo gedit /boot/grub/grub.cfg
然后将下面这段专栏中已经给出的配置粘贴到grub.cfg文件中,并保存
menuentry 'HelloOS' {
insmod part_msdos #GRUB加载分区模块识别分区
insmod ext2 #GRUB加载ext文件系统模块识别ext文件系统
set root='hd0,msdos5' #注意boot目录挂载的分区,这是我机器上的情况
multiboot2 /boot/HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin
boot #GRUB启动HelloOS.bin
}
5.1)设置 multiboot2
multiboo2 '***' 填写的HelloOS.bin的路径,下面以HelloOS.bin放在/boot文件夹下进行举例
首先确认自己的/boot文件夹是独立分区单独挂载还是算在根分区的一部分(一般是配置系统时自己进行分区选择的)。这一步设置不对,会在最后进入HelloOS系统时产生 "HelloOS.bin not found"这个错误
在命令行使用以下命令进行查看分区情况,我将这两种情况下命令运行的结果都展示出来,大家对号入座即可。
df -h

如果是单独挂载的情况,multiboot2设置如下
multiboot2 /HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin

如果是/boot是根分区一部分,multiboot2设置如下
multiboot2 /boot/HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin
总结一下,如果/boot是单独分区的,就可以去掉/boot。
5.2)设置insmod和set root=' '
set root=‘***’里面填写的是存放HelloOS.bin的文件夹,在 三、文件准备 2. 中其实说过,HelloOS.bin文件放在哪里都是可以的,不一定要放在/boot文件夹下。而set root=''中填写的就是存放HelloOS.bin的文件夹所在的磁盘分区。
在专栏的文章中,老师没有详细解释set root=''的具体设置方法,而是给了一个例子,这里我给大家展示最完备的方法。因为我的HelloOS.bin存放在/boot下,所以我们接下来寻找/boot文件夹所在的磁盘分区。同时又分成/boot单独分区与/boot在根目录下两种情况进行讲解
接下来我们要进入grub的命令行模式找寻HelloOS.bin所在文件夹的磁盘分区。重启虚拟机,在重启时长按esc键调出grub引导界面(如果是物理机的请自行搞定调出grub引导界面,能用在物理机上装linux的伙伴肯定能搞定这点小事)
然后按c键进入grub命令行交互模式,并输入ls+回车,列出所有磁盘分区。下面附上一篇文章链接介绍msdos与gpt这两种分区的区别
https://blog.csdn.net/free050463/article/details/81876521
接下来我们分情况讨论,大家自己对号入座 ,灵活修改
5.2.1)虚拟机 + /boot文件夹属于根目录一部分,没有单独分区

在列出磁盘分区后,我们遍历所有磁盘分区里,将分区内文件全部列出来,直到找到看到HelloOS.bin文件为止。同时因为/boot文件夹没有单独分区,那么具体的命令如下
ls (hdx,msdosx)/boot/

那么我们就找到了HelloOS.bin所在的文件夹/boot的磁盘分区,也就确定了set root=''里面的参数为如下
set root="hd0,msdos5"
这是最简单的情况,我猜也是老师实验环境的情况。
然后我们发现磁盘采用msdos分区方式,所以insmod part_msdos 这个配置也就不需要修改了。下面给出完整设置
menuentry 'HelloOS' {
insmod part_msdos #GRUB加载分区模块识别分区
insmod ext2 #GRUB加载ext文件系统模块识别ext文件系统
set root='hd0,msdos5' #注意boot目录挂载的分区,这是我机器上的情况
multiboot2 /boot/HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin
boot #GRUB启动HelloOS.bin
}
5.2.2)物理机 + /boot文件夹单独分区
现在我们就来到了一个比较坑的情况。我先附上grub命令行截图

通过观察可以发现,我的物理机磁盘使用gpt分区方式,所以首先需要做如下修改
insmod part_gpt
然后,因为我的物理机上/boot是单独分区的,所以在进行查找时命令不需要加上/boot,具体命令如下
ls (hdx,gptx)/
我们发现HelloOS.bin在(hd0,gpt5)下面,所以现在可以设置set root了
下面我附上完整设置
menuentry 'HelloOS' {
insmod part_gpt #GRUB加载分区模块识别分区
insmod ext2 #GRUB加载ext文件系统模块识别ext文件系统
set root='hd0,gpt5' #注意boot目录挂载的分区,这是我机器上的情况
multiboot2 /HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin
boot #GRUB启动HelloOS.bin
}
6. 保存grub.cfg,然后重启,在grub引导界面选择HelloOS!大工告成,Oh làààààààà
大家觉得这篇文章有帮助的话可以关注一波up,同时我也在更新LeetCode题解视频,可以来逛逛哟!!
