你好,我是LMOS。
我们知道,在学习许多编程语言一开始的时候,都有一段用其语言编写的经典程序——Hello World。这不过是某一操作系统平台之上的应用程序,却心高气傲地问候世界。
而我们学习操作系统的时候,那么也不妨撇开其它现有的操作系统,基于硬件,写一个最小的操作系统——Hello OS,先练练手、热热身,直观感受一下。
本节课的配套代码,你可以从这里下载。
请注意,这节课主要是演示思路,不要求你马上动手实现。详细的环境安装、配置我们到第十节课再详细展开。有兴趣上手的同学,可以参考留言区置顶的实验笔记探索。
PC机的引导流程
看标题就知道,写操作系统要用汇编和C语言,尽管这个Hello OS很小,但也要用到两种编程语言。其实,现有的商业操作系统都是用这两种语言开发出来的。
先不用害怕,Hello OS的代码量很少。
其实,我们也不打算从PC的引导程序开始写起,原因是目前我们的知识储备还不够,所以先借用一下GRUB引导程序,只要我们的PC机上安装了Ubuntu Linux操作系统,GRUB就已经存在了。这会大大降低我们开始的难度,也不至于打消你的热情。

那在写Hello OS之前,我们先要搞清楚Hello OS的引导流程,如下图所示:

简单解释一下,PC机BIOS固件是固化在PC机主板上的ROM芯片中的,掉电也能保存,PC机上电后的第一条指令就是BIOS固件中的,它负责检测和初始化CPU、内存及主板平台,然后加载引导设备(大概率是硬盘)中的第一个扇区数据,到0x7c00地址开始的内存空间,再接着跳转到0x7c00处执行指令,在我们这里的情况下就是GRUB引导程序。
当然,更先进的UEFI BIOS则不同,这里就不深入其中了,你可以通过链接自行了解。
Hello OS引导汇编代码
明白了PC机的启动流程,下面只剩下我们的Hello OS了,我们马上就去写好它。
我们先来写一段汇编代码。这里我要特别说明一个问题:为什么不能直接用C?
C作为通用的高级语言,不能直接操作特定的硬件,而且C语言的函数调用、函数传参,都需要用栈。
栈简单来说就是一块内存空间,其中数据满足后进先出的特性,它由CPU特定的栈寄存器指向,所以我们要先用汇编代码处理好这些C语言的工作环境。
1 | ;彭东 @ 2021.01.09 |
以上的汇编代码(/lesson02/HelloOS/entry.asm)分为4个部分:
1.代码1~40行,用汇编定义的GRUB的多引导协议头,其实就是一定格式的数据,我们的Hello OS是用GRUB引导的,当然要遵循GRUB的多引导协议标准,让GRUB能识别我们的Hello OS。之所以有两个引导头,是为了兼容GRUB1和GRUB2。
2.代码44~52行,关掉中断,设定CPU的工作模式。你现在可能不懂,没事儿,后面CPU相关的课程我们会专门再研究它。
3.代码54~73行,初始化CPU的寄存器和C语言的运行环境。
4.代码78~87行,GDT_START开始的,是CPU工作模式所需要的数据,同样,后面讲CPU时会专门介绍。
Hello OS的主函数
到这,不知道你有没有发现一个问题?上面的汇编代码调用了main函数,而在其代码中并没有看到其函数体,而是从外部引入了一个符号。
那是因为这个函数是用C语言写的在(/lesson02/HelloOS/main.c)中,最终它们分别由nasm和GCC编译成可链接模块,由LD链接器链接在一起,形成可执行的程序文件:
1 | //彭东 @ 2021.01.09 |
以上这段代码,你应该很熟悉了吧?不过这不是应用程序的main函数,而是Hello OS的main函数。
其中的printf也不是应用程序库中的那个printf了,而是需要我们自己实现了。你可以先停下歇歇,再去实现printf函数。
控制计算机屏幕
接着我们再看下显卡,这和我们接下来要写的代码有直接关联。
计算机屏幕显示往往是显卡的输出,显卡有很多形式:集成在主板的叫集显,做在CPU芯片内的叫核显,独立存在通过PCIE接口连接的叫独显,性能依次上升,价格也是。
独显的高性能是游戏玩家们所钟爱的,3D图形显示往往要涉及顶点处理、多边形的生成和变换、纹理、着色、打光、栅格化等。而这些任务的计算量超级大,所以独显往往有自己的RAM、多达几百个运算核心的处理器。因此独显不仅仅是可以显示图像,而且可以执行大规模并行计算,比如“挖矿”。
我们要在屏幕上显示字符,就要编程操作显卡。
其实无论我们PC上是什么显卡,它们都支持一种叫VESA的标准,这种标准下有两种工作模式:字符模式和图形模式。显卡们为了兼容这种标准,不得不自己提供一种叫VGABIOS的固件程序。
下面,我们来看看显卡的字符模式的工作细节。
它把屏幕分成24行,每行80个字符,把这(24*80)个位置映射到以0xb8000地址开始的内存中,每两个字节对应一个字符,其中一个字节是字符的ASCII码,另一个字节为字符的颜色值。如下图所示:

明白了显卡的字符模式的工作细节,下面我们开始写代码。
这里先提个醒:C语言字符串是以0结尾的,其字符编码通常是utf8,而utf8编码对ASCII字符是兼容的,即英文字符的ASCII编码和utf8编码是相等的(关于utf8编码你可以自行了解)。
1 | //彭东 @ 2021.01.09 |
代码很简单,printf函数直接调用了_strwrite函数,而_strwrite函数正是将字符串里每个字符依次定入到0xb8000地址开始的显存中,而p_strdst每次加2,这也是为了跳过字符的颜色信息的空间。
到这,Hello OS相关的代码就写好了,下面就是编译和安装了。你可别以为这个事情就简单了,下面请跟着我去看一看。
编译和安装Hello OS
Hello OS的代码都已经写好,这时就要进入安装测试环节了。在安装之前,我们要进行系统编译,即把每个代码模块编译最后链接成可执行的二进制文件。
你可能觉得我在小题大做,编译不就是输入几条命令吗,这么简单的工作也值得一说?
确实,对于我们Hello OS的编译工作来说特别简单,因为总共才三个代码文件,最多四条命令就可以完成。
但是以后我们Hello OS的文件数量会爆炸式增长,一个成熟的商业操作系统更是多达几万个代码模块文件,几千万行的代码量,是这世间最复杂的软件工程之一。所以需要一个牛逼的工具来控制这个巨大的编译过程。
make工具
make历史悠久,小巧方便,也是很多成熟操作系统编译所使用的构建工具。
在软件开发中,make是一个工具程序,它读取一个叫“makefile”的文件,也是一种文本文件,这个文件中写好了构建软件的规则,它能根据这些规则自动化构建软件。
makefile文件中规则是这样的:首先有一个或者多个构建目标称为“target”;目标后面紧跟着用于构建该目标所需要的文件,目标下面是构建该目标所需要的命令及参数。
与此同时,它也检查文件的依赖关系,如果需要的话,它会调用一些外部软件来完成任务。
第一次构建目标后,下一次执行make时,它会根据该目标所依赖的文件是否更新决定是否编译该目标,如果所依赖的文件没有更新且该目标又存在,那么它便不会构建该目标。这种特性非常有利于编译程序源代码。
任何一个Linux发行版中都默认自带这个make程序,所以不需要额外的安装工作,我们直接使用即可。
为了让你进一步了解make的使用,接下来我们一起看一个有关makefile的例子:
1 | CC = gcc #定义一个宏CC 等于gcc |
我来解释一下这个例子:
make规定“#”后面为注释,make处理makefile时会自动丢弃。
makefile中可以定义宏,方法是在一个字符串后跟一个“=”或者“:=”符号,引用宏时要用“$(宏名)”,宏最终会在宏出现的地方替换成相应的字符串,例如:$(CC)会被替换成gcc,$( OBJS_FILE) 会被替换成file.o file1.o file2.o file3.o file4.o。
.PHONY在makefile中表示定义伪目标。所谓伪目标,就是它不代表一个真正的文件名,在执行make时可以指定这个目标来执行其所在规则定义的命令。但是伪目标可以依赖于另一个伪目标或者文件,例如:all依赖于everything,everything最终依赖于file.c file1.c file2.c file3.c file4.c。
虽然我们会发现,everything下面并没有相关的执行命令,但是下面有个通用规则:“%.o : %.c”。其中的“%”表示通配符,表示所有以“.o”结尾的文件依赖于所有以“.c”结尾的文件。
例如:file.c、file1.c、file2.c、file3.c、file4.c,通过这个通用规则会自动转换为依赖关系:file.o: file.c、file1.o: file1.c、file2.o: file2.c、file3.o: file3.c、file4.o: file4.c。
然后,针对这些依赖关系,分别会执行:$(CC) $(CFLAGS) -o $@ $<命令,当然最终会转换为:gcc –c –o xxxx.o xxxx.c,这里的“xxxx”表示一个具体的文件名。
编译
下面我们用一张图来描述我们Hello OS的编译过程,如下所示:

安装Hello OS
经过上述流程,我们就会得到Hello OS.bin文件,但是我们还要让GRUB能够找到它,才能在计算机启动时加载它。这个过程我们称为安装,不过这里没有写安装程序,得我们手动来做。
经研究发现,GRUB在启动时会加载一个grub.cfg的文本文件,根据其中的内容执行相应的操作,其中一部分内容就是启动项。
GRUB首先会显示启动项到屏幕,然后让我们选择启动项,最后GRUB根据启动项对应的信息,加载OS文件到内存。
下面来看看我们Hello OS的启动项:
1 | menuentry 'HelloOS' { |
如果你不知道你的boot目录挂载的分区,可以在Linux系统的终端下输入命令:df /boot/,就会得到如下结果:
1 | 文件系统 1K-块 已用 可用 已用% 挂载点 |
其中的“sda4”就是硬盘的第四个分区(硬件分区选择MBR),但是GRUB的menuentry中不能写sda4,而是要写“hd0,msdos4”,这是GRUB的命名方式,hd0表示第一块硬盘,结合起来就是第一块硬盘的第四个分区。
把上面启动项的代码插入到你的Linux机器上的/boot/grub/grub.cfg文件末尾,然后把Hello OS.bin文件复制到/boot/目录下,一定注意这里是追加不是覆盖。最后重启计算机,你就可以看到Hello OS的启动选项了。
选择Hello OS,按下Enter键(或者重启按ESC键),这样就可以成功启动我们自己的Hello OS了。
重点回顾
有没有很开心?我们终于看到我们自己的OS运行了,就算它再简单也是我们自己的OS。下面我们再次回顾下这节课的重点。
首先,我们了解了从按下PC机电源开关开始,PC机的引导过程。它从CPU上电,到加载BIOS固件,再由BIOS固件对计算机进行自检和默认的初始化,并加载GRUB引导程序,最后由GRUB加载具体的操作系统。
其次,就到了我们这节课最难的部分,即用汇编语言和C语言实现我们的Hello OS。
第一步,用汇编程序初始化CPU的寄存器、设置CPU的工作模式和栈,最重要的是加入了GRUB引导协议头;第二步,切换到C语言,用C语言写好了主函数和控制显卡输出的函数,其间还了解了显卡的一些工作细节。
最后,就是编译和安装Hello OS了。我们用了make工具编译整个代码,其实make会根据一些规则调用具体的nasm、gcc、ld等编译器,然后形成Hello OS.bin文件,你把这个文件写复制到boot分区,写好GRUB启动项,这样就好了。
这里只是上上手,下面我们还会去准备一些别的东西,然后就真正开始了。但你此刻也许还有很多问题没有搞清楚,比如重新加载GDT、关中断等,先不要担心,我们后面会一一解决的。
思考题
以上printf函数定义,其中有个形式参数很奇怪,请你思考下:为什么是“…”形式参数,这个形式参数有什么作用?
欢迎你在留言区分享你的思考或疑问。
我是LMOS,我们下节课见!
- Geek_b3ad17 👍(3) 💬(5)
lesson2 运行在bochs 虚拟机 https://gitee.com/jiawenshi/myos
2023-10-17 - 孟祥毅🇨🇳Xiangyi 👍(9) 💬(3)
P.S. 不想每次改完程序重启看效果的同学可以考虑用qemu来boot kernel,之前有两个同学给了solution,但是好像一个制作引导镜像的步骤有点问题,另一个没用grub,用的自定义的bootloader。我follow老师的课程做了个grub版的(包括怎么制作引导镜像)放在了github上 https://github.com/xymeng16/helloOS,不想深究直接make qemu-grub就可以用,想深究的话脚本也都在repo里面~之后我会把联合gdb调试的脚本也加进去,方便找bug...
2021-10-21 - royalfarmer 👍(22) 💬(3)
也来交个作业 既然是从0到1,建议像我一样的小白用户,全部代码自己动手写一遍,哪怕很多细节不懂,但从整体上会有一个感性认识,有了框架,后面慢慢补充相关知识,这样学的会更加牢固。 那些折腾虚拟机直接copy老师的代码,是高手玩的,需要有足够的基本功才玩的转。小白一定要先练好自己的基本功,手动抄代码是练基本功非常好的方法,看一遍和写一遍感觉完全不一样。
操作系统算是比较难的了,开始学习之前,自己得先有些基本的知识储备。
首先,要对Linux有基本概念,会在物理机上装Linux,知道Linux常用的命令,知道怎么在Linux里安装程序。说下我的作业过程:
一、个人PC上直接装的Linux,版本是ubuntu。二、在自己的家目录下新建一个HelloOS文件夹,在里面新建5个文件,文件内容照着老师给的源码全部手抄一遍,一定要仔细,一个字母都不能差:
entry.asm (汇编文件,进行一些针对电脑硬件的操作)
main.c (我们自己这个操作系统的主函数源代码,里面就一个printf函数,功能是我们这个操作系统运行时显示的那句话)
vgastr.c (printf函数的具体实现代码,需要调用到显卡显存)
vgastr.h (主函数的头文件)
Makefile (make命令编译时遵照的格式文件)install.md (确切的说,这是一段代码,有没有这个文件都行,把代码补充到/boot/grub/grub.cfg 文件的末尾,目的是更新grub 引导程序的配置文件,让grub能找到我们的helloOS,评论里出现最多的找不到文件的问题,基本都是这段代码没写对,更确切说,就是那一句 multiboot2 /boot 或改为 multiboot2 / )
三、途中可能会遇到几个问题
1 提示没有装nasm, 无法编译汇编文件 .asm,解决方法,直接根据系统提示,输入命令安装该程序
2 提示make不是命令,无法编译,解决方法,直接根据系统提示,输入命令安装该程序
3 源代码抄写错误,都会有提示具体在哪个文件哪一行,写错字符,缺少横杠,字符大小写等(我甚至都没有用编辑器,抄起来确实比较痛苦,但完成后的成就感也更大)四、补充一个细节,确认完挂载点后,记得把helloOS.bin文件放到挂载点的目录下,要不然,即使grub.cfg配置写对了,仍然会提示找不到文件。
五、有个小问题没搞明白,为啥我生成的helloOS.bin 文件的首字母是小写的?我看别人的截图都是大写的,不过这个貌似不影响系统启动。
2021-09-25 - De_sword 👍(4) 💬(2)
补充一点对于内核文件路径设定的方案。
尝试过@Vic, @陈诚 , 的方案。
进入过grub模式查看硬盘下的路径,但是仍然遇到error : file '/boot/HelloOS.bin' not found的问题。因此,我这边参考了grub.cfg里面,“Ubuntu”的设置:
menuentry 'Ubuntu' –class ubuntu –class gnu-linux –class gnu –class os $menuentry_id_option 'gnulinux-simple-c2b35b75-3fa4-4021-b628-65742342045e' {
insmod gzio
insmod part_msdos
insmod ext2
set root='hd0,msdos1'
initrd /initrd.img-4.4.0-57-generic
}
可以发现,默认载入时就已经以/boot为根目录, 因此,我也照葫芦画瓢,没有额外设定/boot目录。重新启动,就可以成功运行HelloOS内核了。
2021-09-10 - 不安好心 👍(2) 💬(1)
有一个疑问,汇编代码那里: ;重新加载 GDTlgdt [GDT_PTR] jmp dword 0x8 :_32bits_mode 这里明明没有开启保护模式,为什么能这样跳转,而且经验证,也确实使用了gdt。 但是实模式不是cs << 4 + offset进行寻址吗?
2021-08-25 - 喜欢吃鱼 👍(19) 💬(3)
实验注意几个关键问题。
将作者提供的代码git到本地;
安装nasm、gcc等工具,否则make不通过。随后执行“make -f Makefile”,得到HelloOs.bin;
在/boot/grub/grub.cfg中添加如下引导内容:
1
2
3
4
5
6
7menuentry 'HelloOS' {
insmod part_msdos #GRUB加载分区模块识别分区
insmod ext2 #GRUB加载ext文件系统模块识别ext文件系统
set root='hd0,msdos1' #注意boot目录挂载的分区,这是我机器上的情况
multiboot2 /boot/HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin
boot #GRUB启动HelloOS.bin
}#其中set root='hd0,msdos1'根据/boot挂载的实际情况填写,如我的机器是: ubuntu@ubuntu-virtual-machine:~$ df /boot Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda1 20509264 7482912 11961496 39% //usr/local/bin/brew tap nativeos/i386-elf-toolchain /usr/local/bin/brew install i386-elf-binutils i386-elf-gcc nasm qemu1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
- 将HelloOs.bin拷贝到/boot/目录;
- 重启机器,vmvare长按shift进入引导页面,可以看到HelloOS,选择HelloOS进入。</p>2021-07-13</li><br/><li><span>Freddy</span> 👍(9) 💬(10)<p>我用的是CentOS 7虚拟机,有点不一样:
环境说明:
gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
[root@node01 ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
下面是添加HelloOS启动项的流程:
1.在/etc/grub.d/40_custom文件中,添加HelloOS在grub2中的配置
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries. Simply type the
# menu entries you want to add after this comment. Be careful not to change
# the 'exec tail' line above.
#以下是添加内容
menuentry 'HelloOS' {
insmod part_msdos #GRUB加载分区模块识别分区
insmod ext2 #GRUB加载ext文件系统模块识别ext文件系统
set root='hd0,msdos1' #注意boot目录挂载的分区,这是我机器上的情况
multiboot2 /HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin
boot #GRUB启动HelloOS.bin
}
2.重新生成/boot/grub2/grub.cfg文件
[root@node01 grub2]# grub2-mkconfig -o /boot/grub2/grub.cfg
3.重启VM,即可在grub引导项中看到多了HelloOS
</p>2021-05-24</li><br/><li><span>Shinymimiq</span> 👍(58) 💬(7)<p>我测试了一下M1的Mac也是能跑起了HelloOS的,虽然坑比较多。我大致总结了一下步骤:
首先需要安装x86版的homebrew
用Rosetta 打开iTerm
然后安装x86的homebrew
`arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"`
接下来是重点, Apple自带的C/C++工具链是clang,外加用的linker和GUN linker不兼容,没办法使用课程中提供的linker script,所以我们需要编译安装x86的gcc工具链,顺便可以把nasm和qemu给装了
1
2
安装完成之后确认一下我们的gcc和ld/usr/local/Cellar/i386-elf-gcc/9.2.0/bin/i386-elf-gcc
/usr/local/Cellar/i386-elf-binutils/2.31/bin/i386-elf-ld1
2
3
4
5
接下来的步骤我参考了Viz的评论,代码是在
`https://github.com/vizv/learn\_os/tree/master/hello-os`
可以手动修改Makefile里面的宏ASM := /usr/local/Cellar/nasm/2.15.05/bin/nasm
CC := /usr/local/Cellar/i386-elf-gcc/9.2.0/bin/i386-elf-gcc
LD := /usr/local/Cellar/i386-elf-binutils/2.31/bin/i386-elf-ld1
2
顺带一提,我使用iTerm跑还需要在qemu命令上加上-nographic,不然好像没法退出qemu-system-x86_64 -nographic -curses -drive 'file=$<,format=raw,index=0,media=disk'
然后直接`make all`就可以运行我们的hello-os了</p>2021-05-22</li><br/><li><span>青玉白露</span> 👍(14) 💬(5)<p>写了一个基于Vmare和Ubuntu16.04的详细教程,只要手头有电脑就可以运行,大家可以看看: https://zhuanlan.zhihu.com/p/373996858</p>2021-05-21</li><br/><li><span>Viz</span> 👍(38) 💬(9)<p>我也搞了份不需要 GRUB 可以直接用 QEMU 或者其他虚拟机软件跑的版本 https://github.com/vizv/learn_os/tree/master/hello-os 克隆仓库后在 hello-os 目录里 只编译链接并创建镜像: make hello-os.img 编译链接并创建镜像后用 QEMU 启动磁盘镜像: make</p>2021-05-15</li><br/><li><span>Strangeen🚁</span> 👍(79) 💬(18)<p>我是小白,只会java,没学过c,当时也只是抱着了解下操作系统的想法报了课程,学到第2课,发现完全听不懂... 不过跟着课程和陈诚的博客走(https://blog.csdn.net/chenchengwudi/article/details/116707122),然后下载了老师的代码,最终居然还是跑出Hello OS!来了,虽然还不太明白汇编、Makefile、hello.lds代码的含义... 看来又多了一份学下去的信心了! 我是在mac pro(os 10.15.6)上使用parallel安装的ubuntu kylin 18.04,这里我要对像我这样的小白说3个点: 1、安装nasm,才能执行make 先安装nasm:sudo apt-get install -y nasm 然后在HelloOS目录下执行:make -f Makefile 就可以得到HelloOS.bin文件了 2、一定要按照陈诚的博客的2.1中配置下启动项,不然无法选择HelloOS菜单 先修改文件:/etc/default/grub 然后执行:sudo update-grub 3、menuentry直接添加到grub.cfg文件的末尾即可</p>2021-05-15</li><br/><li><span>胡永</span> 👍(43) 💬(14)<p>补充两个我遇到的坑: 1. 如何确定boot挂载的分区,参考Geek_993581提供的方法,在grub命令行里确认。 set root='hd0,msdos4' #注意boot目录挂载的分区,修改为自己的分区。 我自己的是(hd0,gpt2)。 把insmod part_msdos 修改为 part_gpt。 2. 很多同学遇到说HelloOS.bin找不到 这个就是要确认boot的挂在路径是/还是/boot 文件系统 1K-块 已用 可用 已用% 挂载点 /dev/sda4 48752308 8087584 38158536 18% / 如果跟老师一样,不用修改。 但是如果挂载点是/boot,需要把路径改为multiboot2 /HelloOS.bin 当然你也可以在grub命令行里面确认, 如果ls (hd0,gpt2)/boot 找不到boot目录,就 ls (hd0,gpt2)/,如果能看到HelloOS.bin,说明grub把boot设为root,路径前面不需要加boot了。</p>2021-05-13</li><br/><li><span>Eevee</span> 👍(9) 💬(1)<p>将自己遇到的几个小问题总结下,希望能帮助到其他同学(linux新手) 1. 将HelloOs.bin移动到boot文件夹时无权限 解决办法:打开终端,运行命令sudo nautilus就可以打开一个管理员权限的文件管理器 2.df/boot/失效 解决办法:df-h 查看所有文件挂载,找到boot即可 3.nasm安装,参考教程https://blog.csdn.net/qq_44641344/article/details/104355359?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&spm=1001.2101.3001.4242 </p>2021-05-13</li><br/><li><span>Bo</span> 👍(10) 💬(2)<p>在输入df /boot/ 时,要注意下【挂载点】的值是/还是/boot,东哥这里是/;如果是/boot,就要注意在修改/boot/grub/grub.cfg文件时,multiboot2这一项直接填写/HelloOS.bin即可,而不需要在前面加/boot了,因为/boot被划分为单独的分区了,即: multiboot2 /HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin 此外,还可以参考楼上Geek_993581的回答去验证HelloOS.bin的位置</p>2021-05-13</li><br/><li><span>第九天魔王</span> 👍(19) 💬(1)<p>实际上boot目录只是一个目录,helloos文件可以放到其它目录,只要把grub.cfg里面相应位置改下就行了。把内核文件放到boot目录是一个既定的做法,目录下面有个vmlinuz-xxx就是Ubuntu的内核镜像。另外grub本身带有ext驱动,所以可以访问文件系统,取出你的内核镜像执行。</p>2021-05-13</li><br/> </ul>