极客时间已完结课程限时免费阅读

10 | 设置工作模式与环境(上):建立计算机

10 | 设置工作模式与环境(上):建立计算机-极客时间

10 | 设置工作模式与环境(上):建立计算机

讲述:陈晨

时长11:45大小10.73M

你好,我是 LMOS。
经过前面那么多课程的准备,现在我们距离把我们自己操作系统跑起来,已经是一步之遥了。现在,你是不是很兴奋,很激动?有这些情绪说明你是喜欢这门课程的。
接下来的三节课,我们会一起完成一个壮举,从 GRUB 老大哥手中接过权柄,让计算机回归到我们的革命路线上来,为我们之后的开发自己的操作系统做好准备。
具体我是这样来安排的,今天这节课,我们先来搭好操作系统的测试环境。第二节课,我们一起实现一个初始化环境的组件——二级引导器,让它真正继承 GRUB 权力。第三节课,我们正式攻下初始化的第一个山头,对硬件抽象层进行初始化。
好,让我们正式开始今天的学习。首先我们来解决内核文件封装的问题,然后动手一步步建好虚拟机和生产虚拟硬盘。课程配套代码你可以在这里下载。

从内核映像格式说起

我们都知道,一个内核工程肯定有多个文件组成,为了不让 GRUB 老哥加载多个文件,因疲劳过度而产生问题,我们决定让 GRUB 只加载一个文件。
但是要把多个文件变成一个文件就需要封装,即把多个文件组装在一起形成一个文件。这个文件我们称为内核映像文件,其中包含二级引导器的模块,内核模块,图片和字库文件。为了这映像文件能被 GRUB 加载,并让它自身能够解析其中的内容,我们就要定义好具体的格式。如下图所示。
内核映像文件格式
上图中的 GRUB 头有 4KB 大小,GRUB 正是通过这一小段代码,来识别映像文件的。另外,根据映像文件头描述符和文件头描述符里的信息,这一小段代码还可以解析映像文件中的其它文件。
映像文件头描述符和文件描述符是两个 C 语言结构体,如下所示。
//映像文件头描述符
typedef struct s_mlosrddsc
{
u64_t mdc_mgic; //映像文件标识
u64_t mdc_sfsum;//未使用
u64_t mdc_sfsoff;//未使用
u64_t mdc_sfeoff;//未使用
u64_t mdc_sfrlsz;//未使用
u64_t mdc_ldrbk_s;//映像文件中二级引导器的开始偏移
u64_t mdc_ldrbk_e;//映像文件中二级引导器的结束偏移
u64_t mdc_ldrbk_rsz;//映像文件中二级引导器的实际大小
u64_t mdc_ldrbk_sum;//映像文件中二级引导器的校验和
u64_t mdc_fhdbk_s;//映像文件中文件头描述的开始偏移
u64_t mdc_fhdbk_e;//映像文件中文件头描述的结束偏移
u64_t mdc_fhdbk_rsz;//映像文件中文件头描述的实际大小
u64_t mdc_fhdbk_sum;//映像文件中文件头描述的校验和
u64_t mdc_filbk_s;//映像文件中文件数据的开始偏移
u64_t mdc_filbk_e;//映像文件中文件数据的结束偏移
u64_t mdc_filbk_rsz;//映像文件中文件数据的实际大小
u64_t mdc_filbk_sum;//映像文件中文件数据的校验和
u64_t mdc_ldrcodenr;//映像文件中二级引导器的文件头描述符的索引号
u64_t mdc_fhdnr;//映像文件中文件头描述符有多少个
u64_t mdc_filnr;//映像文件中文件头有多少个
u64_t mdc_endgic;//映像文件结束标识
u64_t mdc_rv;//映像文件版本
}mlosrddsc_t;
#define FHDSC_NMAX 192 //文件名长度
//文件头描述符
typedef struct s_fhdsc
{
u64_t fhd_type;//文件类型
u64_t fhd_subtype;//文件子类型
u64_t fhd_stuts;//文件状态
u64_t fhd_id;//文件id
u64_t fhd_intsfsoff;//文件在映像文件位置开始偏移
u64_t fhd_intsfend;//文件在映像文件的结束偏移
u64_t fhd_frealsz;//文件实际大小
u64_t fhd_fsum;//文件校验和
char fhd_name[FHDSC_NMAX];//文件名
}fhdsc_t;
有了映像文件格式,我们还要有个打包映像的工具,我给你提供了一个 Linux 命令行下的工具(在 Gitee 代码仓库中,通过这个链接获取),你只要明白使用方法就可以,如下所示。
lmoskrlimg -m k -lhf GRUB头文件 -o 映像文件 -f 输入的文件列表
-m 表示模式 只能是k内核模式
-lhf 表示后面跟上GRUB头文件
-o 表示输出的映像文件名
-f 表示输入文件列表
例如:lmoskrlimg -m k -lhf grubhead.bin -o kernel.img -f file1.bin file2.bin file3.bin file4.bin

准备虚拟机

打包好了映像文件,我们还有很重要的一步配置——准备虚拟机。这里你不妨先想一想,开发应用跟开发操作系统有什么不同呢?
在你开发应用程序时,可以在 IDE 中随时编译运行应用程序,然后观察结果状态是否正确,中间可能还要百度一下查找相关资料,不要笑,这是大多数人的开发日常。但是你开发操作系统时,不可能写 5 行代码之后就安装在计算机上,重启计算机去观察运行结果,这非常繁琐,也很浪费时间。
好在我们有虚拟机这个好帮手。虚拟机用软件的方式实现了真实计算机的全部功能特性,它在我们所使用的 Linux 下,其实就是个应用程序。
使用虚拟机软件我们就可以在现有的 Linux 系统之上开发、编译、运行我们的操作系统了,省时且方便。节约的时间我们可以喝茶、听听音乐、享受美好生活。

安装虚拟机

这里我们一致约定使用甲骨文公司的VirtualBox虚拟机。经过测试,我发现 VirtualBox 虚拟机有很多优点,它的功能相对完善、性能强、BUG 少,而且比较稳定。
在现代 Linux 系统上安装 VirtualBox 虚拟机是非常简单的,你只要在 Linux 发行版中找到其应用商店,在其中搜索 VirtualBox 就行了。我们作为专业人士一条命令可以解决的事情,为什么要用鼠标点来点去呢,多浪费时间。
所以,你只要在终端中输入如下命令就行了,我假定你安装了 Ubuntu 系的 Linux 发行版,这里 Ubuntu 的版本不做规定。
sudo apt-get install virtualbox-6.1
运行 Virtualbox 后,如果出现如下界面,就说明安装 VirtualBox 成功了。
安装VirtualBox

建立虚拟电脑

前面我们只是安好了虚拟机管理软件,我们还要新建虚拟机才可以。点击上图中的新建,然后选择专家模式,就可以进入专家模式配置我们的电脑了。
尽管它是虚拟的,我们还是可以选择 CPU 类型、内存大小、硬盘大小、网络等配置,为了一致性,请你按照如下截图来配置。
新建虚拟机
新建虚拟机
可以看到,我们选择了 64 位的架构,1024MB 内存,但是不要添加硬盘,后面自有妙用。显卡是 VBoxVGA,还有硬件加速,这会让虚拟机调用我们机器上真实的 CPU 来运行我们的操作系统。

手工生产硬盘

上面的虚拟机中还没有硬盘,没有硬盘虚拟机就没地方加载数据,我们当然不是要买一块硬盘挂上去,而是要去手工生产一块硬盘。你马上就会发现,从零开始生产一块虚拟硬盘,这比从零开始写一个操作系统简单得多。
至于为什么手工生产硬盘,我先卖个关子,你看完这部分内容就能找到答案。
其实大多数虚拟机都是用文件来模拟硬盘的,即主机系统(HOST OS 即你使用的物理机系统 )下特定格式的文件,虚拟机中操作系统的数据只是写入了这个文件中。

生产虚拟硬盘

其实虚拟机只是用特定格式的文件来模拟硬盘,所以生产虚拟硬盘就变成了生成对应格式的文件,这就容易多了。我们要建立 100MB 的硬盘,这意味着要生成 100MB 的大文件。
下面我们用 Linux 下的 dd 命令(用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换)生成 100MB 的纯二进制的文件(就是 1~100M 字节的文件里面填充为 0 ),如下所示。
dd bs=512 if=/dev/zero of=hd.img count=204800
;bs:表示块大小,这里是512字节
;if:表示输入文件,/dev/zero就是Linux下专门返回0数据的设备文件,读取它就返回0
;of:表示输出文件,即我们的硬盘文件。
;count:表示输出多少块
执行以上命令就可以生成 100MB 的文件。文件数据为全 0。由于我们不用转换数据,就是需要全 0 的文件,所以 dd 命令只需要这几个参数就行。

格式化虚拟硬盘

虚拟硬盘也需要格式化才能使用,所谓格式化就是在硬盘上建立文件系统。只有建立了文件系统,现有的成熟操作系统才能在其中存放数据。
可是,问题来了。虚拟硬盘毕竟是个文件,如何让 Linux 在一个文件上建立文件系统呢?这个问题我们要分成三步来解决。
第一步,把虚拟硬盘文件变成 Linux 下的回环设备,让 Linux 以为这是个设备。其实在 Linux 下文件可以是设备,设备可以是文件。下面我们用 losetup 命令,将 hd.img 变成 Linux 的回环设备,代码如下。
sudo losetup /dev/loop0 hd.img
第二步,将 losetup 命令用于设置回环设备。回环设备可以把文件虚拟成 Linux 块设备,用来模拟整个文件系统,让用户可以将其看作硬盘、光驱或软驱等设备,并且可用 mount 命令挂载当作目录来使用。
我们可以用 Linux 下的 mkfs.ext4 命令格式化这个 /dev/loop0 回环块设备,在里面建立 EXT4 文件系统。
sudo mkfs.ext4 -q /dev/loop0
第三步,我们用 Linux 下的 mount 命令,将 hd.img 文件当作块设备,把它挂载到事先建立的 hdisk 目录下,并在其中建立一个 boot,这也是后面安装 GRUB 需要的。如果能建立成功,就说明前面的工作都正确完成了。
说到这里,也许你已经想到了我们要手工生成硬盘的原因。这是因为 mount 命令只能识别在纯二进制文件上建立的文件系统,如果使用虚拟机自己生成的硬盘文件,mount 就无法识别我们的文件系统了。
sudo mount -o loop ./hd.img ./hdisk/ ;挂载硬盘文件
sudo mkdir ./hdisk/boot/ ;建立boot目录
进行到这里,我们会发现 hdisk 目录下多了一个 boot 目录,这说明我们挂载成功了。

安装 GRUB

正常安装系统的情况下,Linux 会把 GRUB 安装在我们的物理硬盘上,可是我们现在要把 GRUB 安装在我们的虚拟硬盘上,而且我们的操作系统还没有安装程序。所以,我们得利用一下手上 Linux(HOST OS),通过 GRUB 的安装程序,把 GRUB 安装到指定的设备上(虚拟硬盘)。
想要安装 GRUB 也不难,具体分为两步,如下所示。
第一步挂载虚拟硬盘文件为loop0回环设备
sudo losetup /dev/loop0 hd.img
sudo mount -o loop ./hd.img ./hdisk/ ;挂载硬盘文件
第二步安装GRUB
sudo grub-install --boot-directory=./hdisk/boot/ --force --allow-floppy /dev/loop0
;--boot-directory 指向先前我们在虚拟硬盘中建立的boot目录。
;--force --allow-floppy :指向我们的虚拟硬盘设备文件/dev/loop0
可以看到,现在 /hdisk/boot/ 目录下多了一个 grub 目录,表示我们的 GRUB 安装成功。请注意,这里还要在 /hdisk/boot/grub/ 目录下建立一个 grub.cfg 文本文件,GRUB 正是通过这个文件内容,查找到我们的操作系统映像文件的。
我们需要在这个文件里写入如下内容。
menuentry 'HelloOS' {
insmod part_msdos
insmod ext2
set root='hd0,msdos1' #我们的硬盘只有一个分区所以是'hd0,msdos1'
multiboot2 /boot/HelloOS.eki #加载boot目录下的HelloOS.eki文件
boot #引导启动
}
set timeout_style=menu
if [ "${timeout}" = 0 ]; then
set timeout=10 #等待10秒钟自动启动
fi

转换虚拟硬盘格式

你可能会好奇,我们前面好不容易生产了 mount 命令能识别的虚拟硬盘,这里为什么又要转换虚拟硬盘的格式呢?
这是因为这个纯二进制格式只能被我们使用的 Linux 系统识别,但不能被虚拟机本身识别,但是我们最终目的却是让这个虚拟机加载这个虚拟硬盘,从而启动其中的由我们开发的操作系统。
好在虚拟机提供了专用的转换格式的工具,我们只要输入一行命令即可。
VBoxManage convertfromraw ./hd.img --format VDI ./hd.vdi
;convertfromraw 指向原始格式文件
;--format VDI 表示转换成虚拟需要的VDI格式

安装虚拟硬盘

好了,到这里我们已经生成了 VDI 格式的虚拟硬盘,这正是我们虚拟机所需要的。然而虚拟硬盘必须要安装虚拟机才可以运行,也就是这个 hd.vdi 文件要和虚拟机软件联系起来。
因为我们之前在建立虚拟机时并没有配置硬盘相关的信息,所以这里需要我们进行手工配置。
配置虚拟硬盘分两步:第一步,配置硬盘控制器,我们使用 SATA 的硬盘,其控制器是 intelAHCI;第二步,挂载虚拟硬盘文件。
具体操作如下所示。
#第一步 SATA的硬盘其控制器是intelAHCI
VBoxManage storagectl HelloOS --name "SATA" --add sata --controller IntelAhci --portcount 1
#第二步
VBoxManage closemedium disk ./hd.vdi #删除虚拟硬盘UUID并重新分配
#将虚拟硬盘挂到虚拟机的硬盘控制器
VBoxManage storageattach HelloOS --storagectl "SATA" --port 1 --device 0 --type hdd --medium ./hd.vdi
因为 VirtualBox 虚拟机用 UUID 管理硬盘,所以每次挂载硬盘时,都需要删除虚拟硬盘的 UUID 并重新分配。

最成功的失败

现在硬盘也安装好了,下面终于可以启动我们的虚拟电脑了,我们依然通过命令启动,在 Linux 终端中输入如下命令就可以了。
VBoxManage startvm HelloOS #启动虚拟机
输入以上命令就会出现以下界面,出现 GRUB 引导菜单。
虚拟机启动
直接按下回车键,就能选择我们的 HelloOS,GRUB 就会加载我们的 HelloOS,但是会出现如下错误。
虚拟机GRUB未找到文件
上面的错误显示,GRUB 没有找到 HelloOS.eki 文件,这是因为我们从来没有向虚拟硬盘中放入 HelloOS.eki 文件,所以才会失败。
但这是我们最成功的失败,因为我们配置好了虚拟机,手动建造了硬盘,并在其上安装了 GRUB,到这里我们运行测试环境已经准备好了。
其实你不必太过担心,等我们完成了二级引导器的时候,这个问题会迎刃而解。

重点回顾

希望今天这节课给你带来成就感,虽然我们才走出了万里长征的第一步。为了这一步我们准备了很多。但是我们始终没忘记这一课程的目的,即我们要从 GRUB 老大哥手里接过权柄,控制计算机王国,为此,我们完成了后面这三个工作。
我们了解了内核映像格式,以便我们对编译产生的内核程序文件进行封装打包。
为了方便测试我们的操作系统,我们了解并安装了虚拟机。
手动建立了虚拟硬盘,对其格式化,在其中手动安装了 GRUB 引导器,并且启动了虚拟电脑。
虽然我们启动虚拟电脑失败了,但是对我们而言却是巨大的成功,因为它标志着我们测试运行内核的环境已经成功建立,下一课我们将继续实现二级引导器。

思考题

请问,我们为什么要把虚拟硬盘格式化成 ext4 文件系统格式呢?
欢迎你在留言区跟我交流探讨,如果你身边有对写操作系统感兴趣的朋友,也欢迎把这节课分享给他,一起学习。
好,我是 LMOS,我们下节课见!
分享给需要的人,Ta购买本课程,你将得20
生成海报并分享

赞 39

提建议

上一篇
09 | 瞧一瞧Linux:Linux的自旋锁和信号量如何实现?
下一篇
11 | 设置工作模式与环境(中):建造二级引导器
unpreview
 写留言

精选留言(117)

  • 第九天魔王
    置顶
    2021-05-31
    已完成实验,有几个心得分享一下。 1,如果主机就是Linux比如Ubuntu,则完全按照东哥的教程做即可,即Linux主机安装虚拟机启动HelloOS。 2,如果主机是Windows,启动虚拟机运行Ubuntu,很多童鞋担心虚拟机Ubuntu里再运行虚拟机启动HelloOS,这样就会套娃。其实可以避免套娃的。在你的虚拟机,也就是Ubuntu环境下,完成hd.img的创建,文件系统的格式化,grub的安装后,生成最终的hd.img文件。然后把hd.img文件通过命令变成vdi文件即可。然后在你的WIN主机环境下,新建一个虚拟机,加载vdi即可。也就是说此时HelloOS和Ubuntu都是你WIN环境下并列的两个虚拟机,这样就可以避免套娃了。 3,如果虚拟机使用的不是VirtualBox, 面是vmware,在生成hd.img后,可以使用starwindconverter工具(网上下载,WIN下运行),这个工具可以把img转换为各种格式,比如vmware的vmdk文件。然后vmware创建一个新的虚拟机,硬盘选择这个vmdk文件,就可以加载HelloOS了。 4,如果HelloOS加载成功,但是提示'hd0,msdos1'错误,则重新制作镜像,并且修改grub.cfg里的这行为'hd0,msdos1'为'hd0'即可。
    展开

    编辑回复: 6666。十分感谢你的分享,已置顶供后面同学参考。

    共 14 条评论
    124
  • neohope
    置顶
    2021-06-01
    【更新】对于使用Windows、MacOS的同学,或不熟悉命令行的同学可以这样操作【不需要套娃,也不用做硬盘格式转换】: 1、先安装一个Linux虚拟机A,比如Ubuntu18或Ubuntu20 2、关闭虚拟机,在这个虚拟机上,用向导添加一个新硬盘hd.vdi 3、启动虚拟机A 4、创建新硬盘挂载目录 cd ~ mkdir hdisk 5、挂载新硬盘,创建ext4文件系统【当前应该只有两块硬盘,所以操作sdb,根据你实际情况调整】 sudo mkfs.ext4 /dev/sdb sudo mount /dev/sdb hdisk 6、创建boot目录 sudo mkdir hdisk/boot 7、安装grub到新硬盘 sudo grub-install --boot-directory=./hdisk/boot/ --force --allow-floppy /dev/sdb 8、拷贝HelloOS.eki到hdisk/boot目录 9、创建grub.cfg,用你喜欢的编辑器就好【其中root可以只写'hd0'】 sudo vi hdisk/boot/grub/grub.cfg 10、关闭虚拟机A 11、创建虚拟机B,选择类型“其他Linux”,硬盘不要新建,直接选择hd.vdi 12、开启虚拟机B,就可以看到Grub界面了 以后要发布内容,就关闭虚拟机B,开启虚拟机A进行操作; 要看效果,就关闭虚拟机A,开启虚拟机B; 硬盘以后也不需要重复创建,只要保证A、B不同时开启就好了;
    展开

    作者回复: 谢谢你的分享,让更多的同学明白了 如何 建立 环境

    共 19 条评论
    64
  • Vic
    置顶
    2021-06-05
    终于试成功了,真开心,断断续续搞了快一个星期。 因为我的主机是mac, 谢谢第九天魔王大、neohoped大和老王大的分享,免去套娃,少走很多弯路。 0.在主机Mac上安装 Virtual Box 6.1,开了2个虚拟机: 虚拟机1: HelloOS 虚拟机2: Linux Ubuntu 20.04 (server) 1. 依照老师课程介绍安装虚拟机1: HelloOS 2. 新增虚拟机2: Linux Ubuntu 20.04 但建议网络可用bridge 桥接模式不用缺省的NAT,方便从虛擬機2傳檔案到mac 主機。 例如我的虚拟机2的网络设定: 连接方式:桥接网卡 界面名称: en0: Wi-Fi (AirPort) 3. 启动虛擬機2 在家目錄执行以下命令建立虚拟磁碟 dd bs=512 if=/dev/zero of=hd.img count=204800 4. sudo losetup /dev/loop0 hd.img 会遇到losetup: hd.img: failing to set up loop device: Device or resource busy 可執行以下命令查看: sudo losetup 列出 /dev/loop0 到 /dev/loop5都被使用了, 挑一个没人用的例如: /dev/loop6 sudo losetup /dev/loop6 hd.img 5. 进行格式化:请依照实际使用的loop设备号码更改,我这里用的是/dev/loop6 sudo mkfs.ext4 -q /dev/loop6 6. 建立hdisk目录 mkdir hdisk 挂载硬盘文件 sudo mount -o loop ./hd.img ./hdisk/ 建立boot目录 sudo mkdir ./hdisk/boot/ 7. 安装grub 请依照实际使用的loop设备号码更改,我这里用的是/dev/loop6 sudo grub-install --boot-directory=./hdisk/boot/ --force --allow-floppy /dev/loop6 8. 创建grub.cfg 安装好grub,应该可看到 ./hdisk/boot/ 下多了一个grub目录, cd 进去 ./hdisk/boot/grub/ 里面没有grub.cfg,要自行创建,文件内容请参考老师课程 9. 回到mac上 将虚拟机2上刚做好的hd.img 透过scp 传回我的mac,例如: scp [[email protected]](mailto:[email protected]):hd.img . (hd.img是放在虚拟机2的家目录,最后有个小点,表示将档案拷到现在这个目录) 10. 转换虚拟机1要用的硬盘格式为VDI 在mac上执行 VBoxManage convertfromraw ./hd.img --format VDI ./hd.vdi 此时应可看到除了原来的hd.img,多了一个hd.vdi的档案 (约13MB) 11. 在mac的/Users/vic/VirtualBox VMs目录执行以下命令: VBoxManage storagectl HelloOS --name "SATA" --add sata --controller IntelAhci --portcount 1 VBoxManage closemedium disk ./hd.vdi VBoxManage storageattach HelloOS --storagectl "SATA" --port 1 --device 0 --type hdd --medium ./hd.vdi 12. 在mac 上执行 VBoxManage startvm HelloOS 13. 如果看到虚拟机1 的GRUB 菜单画面出现 *HelloOS 按下回车键看到 error: file '/boot/HelloOS.eki' not found. error: you need to load the kernel first. 就大功告成 谢谢老师的精彩课程
    展开

    作者回复: 你好,你的经验可以多多分享

    共 19 条评论
    52
  • Jayying
    置顶
    2021-07-31
    终于显示出来了。 记录一下我遇到的几个问题: 1. grub-install时遇到EFI的问题, 添加 参数 --target i386-pc 2. 挂载/dev/loop0时可能遇到device busy, 换一个就行了,比如loop8 3. 进入了grub,但是没有看到HelloOS;这个是我自己头铁,把老师第二行命令删掉了,因为每次执行这条命令都会报错, 按老师的命令写就可以了: VBoxManage closemedium disk ./hd.vdi #删除虚拟硬盘UUID并重新分配 4. 看到HelloOS,但是进入显示找不到hd0,msdos1什么的。在我第三步坑那里,我ls看到的是hd0,所以把hd0,msdos1改成hd0就可以了
    展开

    作者回复: 老铁 666啊

    共 5 条评论
    15
  • Vic
    置顶
    2021-06-05
    超过2000字,补发 后记: 卡了很久,可以看到GRUB,但看不到*HelloOS 2个疑点: (1)在虚拟机2里/dev/loop0被占用,改用/dev/loop6,是不是还有哪里要改,没改对 (2)在grub-install时遇到 ext2 不support embedding的警告 grub-install: warning: File system `ext2' doesn't support embedding. grub-install: warning: Embedding is not possible. GRUB can only be installed in this setup by using blocklists. However, blocklists are UNRELIABLE and their use is discouraged.. Installation finished. No error reported. 但在物理机18.04也遇到,但不影响,只是个警告(warning),不碍事。 才发现自己grub.cfg放错位置,放在hdisk/boot/,而不是放在hdisk/boot/grub里 谢谢老师的精彩教程
    展开

    作者回复: 你好,这个警告可以忽略

    共 4 条评论
    12
  • 青玉白露
    置顶
    2021-07-15
    参考neohope的方法,其实在Mac和Windows环境下利用VirtualBox可以很方便的进行测试, 只需要建立两个虚拟机,一个ubuntu一个是我们的COSMOS,自己在Mac上进行了测试,具体的细节可以参考博客: https://blog.csdn.net/ll15982534415/article/details/118771286

    作者回复: 哈哈 阔以

    8
  • springXu
    置顶
    2021-05-31
    这节课是环境搭建的操作步骤,还没开始真正的动手写代码的要求。 这些操作首先生成内核文件kernel.img文件,这个文件应该是启动的文件。猜测把这个改成HelloOS.eki文件放到grub配置的目录下,不会出现not found的提示。至于显示什么操作就知道了。 二级引导器应该是initldrimh.bin文件的内容。 这部分内容估计是下节课要讲节的内容吧。 三个文件,一个汇编文件用于生成grub格式的头文件,两个.c的文件。 周三继续听下文播讲。 为什么用ext4是为了grub读取的支持?又或者cosmos系统支持ext4的文件系统?
    展开

    作者回复: 用文件系统 是为了linux可以像其中写入文件(我们的内核)

    共 3 条评论
    8
  • Fx
    置顶
    2021-08-26
    ## Ubuntu18.04最全排坑指南 1. virtualbox安装问题无法定位资源包,直接'sudo apt-get install virtualbox', 不要指定版本,安装后版本为5.2.42,目前不影响实验 2. loop资源占用问题,参考前面的评论 3. grub安装时efi方式启动出现问题,指定 '--target i386-pc'出现找不到该文件,若能在系统文件中找到该文件则指定路径查找即可 ``` cd /tmp # 进入efi所在的文件夹,名字可能会不一样,按照报错查找不到的路径为准 sudo apt-get download grub-pc-bin dpkg-deb -R grub-pc-bin_2.02~beta2-36ubuntu3.16_amd64.deb grub/ sudo mv grub/usr/lib/grub/i386-pc/ /usr/lib/grub/ ``` 4. 在执行步骤时我一开始是直接忽略了3,继续往下也不会出现报错,但最后启动虚拟机时出现'FATAL:No bootable medium ....',查看评论需要重新创建虚拟硬盘,于是直接在文件系统删除新建立的能看到的文件,并重启计算机,就能从头开始,否则会出现某些文件已存在的报错但不知道如何删除。最终解决了坑三成功完成实验。
    展开

    作者回复: 666666

    6
  • Shinymimiq
    置顶
    2021-06-11
    我来优化一下Mac小伙伴的开发流程,直接能用Mac编译,并修改我们Cosmos的硬盘镜像文件了,基本可以不需要启动Ubuntu虚拟机了。 首先得按评论区里Veek或者Neohoped大佬的教程得到一个hd.vdi之类的镜像文件 然后使用 Virtual Box 提供的 VBoxManage clonehd 命令,把它转成 raw image VBoxManage clonehd ~/VirtualBox\ VMs/MyUbuntu/hd.vdi image.img --format raw 这时候在 Virtual Box 的 Virtual Media Manager 里是会多一个image.img的硬盘 然后我们只要把Cosmos虚拟机的启动硬盘改成这个image.img就行了 我们修改完OS代码之后,可以把 image.img 加载到 MacOS 系统中 最简单的方式是这样 open image.img 这时候系统的 /Volumes 目录下会多出一个 Untitled 1 文件夹(如果你没有其他 Untitled 镜像加载的话) 之后就可以把相关文件比如 Cosmos.eki 拷贝到 /Volumes/Untitled\ 1/boot 下 完成修改之后,接着使用 umount /Volumes/Untitled\ 1 来取消镜像文件的加载 这时候再启动我们的Cosmos虚拟机就是直接跑更新后的文件了。 至于编译源代码的话,我们可以使用Docker来帮助我们生成一个基于Linux x64的工具链,这样就能直接编译,并且能直接使用课程中提供的 lmoskrlimg,(原来因为文件格式的问题在Mac下无法直接使用这个工具) 首先安装好Docker Desktop 随便新建一个目录 mkdir cosmos_build_env 在里面创建一个Dockerfile, 我在这里直接把内容echo到新文件里面 echo "FROM dockcross/linux-x64 ENV DEFAULT_DOCKCROSS_IMAGE cosmos_build RUN apt-get install -y nasm" > cosmos_build_env/Dockerfile 接下来创建 Docker image docker build cosmos_build_env -t cosmos_build 创建完之后使用 docker run cosmos_build > cosmos_build chmod +x cosmos_build 然后得到的这个cosmos_build就可以用来编译我们的cosmos 例如 ./cosmos_build make release
    展开

    作者回复: 你好,这个厉害了

    共 4 条评论
    6
  • Chaos
    置顶
    2022-04-15
    没想到这一个步骤花费了好几天,现在成功在mac m1的CPU环境下通过QEMU跑起来了hello world。相关细节可以查看我的仓库https://github.com/Rlyown/ToyOS。 这里简要说明一下:成功的关键是借助了Docker和QEMU。Docker可以通过创建x86的Linux容器来完成ext4磁盘的分区、格式化以及安装grub。而QEMU则是用来启动内核的虚拟机。 以下步骤均在x86的容器中完成: 1. 通过命令创建磁盘镜像,本人选择之创建32M的镜像 dd if=/dev/zero of=$DISK bs=512 count=$((32 * 1024 * 1024 / 512)) 2. 对磁盘进行分区,这里只做了一个分区。分区的目的是避免后续执行grub-install安装时报错。 parted -s $DISK mklabel msdos parted -s $DISK mkpart primary 2048s 100% parted -s $DISK set 1 boot on 3. 查找一个空闲的回环设备映射到镜像文件,假设是/dev/loop0 losetup --find --show --partscan ${DISK} 4. 如果像我一样是arm架构借助了x86容器,那么这个步骤很关键。因为容器出于某种原因,映射了带分区的镜像文件后,找不到类似/dev/loop0p1的分区设备。这一步就是手动创建这个分区设备。 PARTITIONS=$(lsblk --raw --output "MAJ:MIN" --noheadings ${LOOPDEV} | tail -n +2) COUNTER=1 for i in $PARTITIONS; do MAJ=$(echo $i | cut -d: -f1) MIN=$(echo $i | cut -d: -f2) if [ ! -e "${LOOPDEV}p${COUNTER}" ]; then mknod ${LOOPDEV}p${COUNTER} b $MAJ $MIN; fi COUNTER=$((COUNTER + 1)) done 5. 格式化分区。 mkfs.ext4 -q /dev/loop0p1 6. 后面就可以挂载这个分区,然后安装grub。这里注意挂载时使用的设备是分区/dev/loop0p1,而进行grub-install时使用的设备是镜像/dev/loop0。 mkdir ISO mount /dev/loop0p1 ISO mkdir -p ISO/boot/grub grub-install --boot-directory=ISO/boot --force --allow-floppy --target=i386-pc /dev/loop0 cp grub.cfg ISO/boot/grub 7. 取消挂载和映射,并删除手动创建的分区设备。 umount ISO lostup -d /dev/loop0 rm -f /dev/loop0p1 8. 通过qemu模拟x86虚拟机 qemu-system-i386 -m 1024 -drive format=raw,file=disk.img
    展开

    作者回复: 太强了

    共 2 条评论
    3
  • 黎标松
    置顶
    2021-07-22
    第一次留言: 我的宿主机是windows 10系统,用系统自带的Hyper-V虚拟机跑ubuntu,为了和老师一致,我又下了vitural Box,按照老师的步骤键虚拟机,这样避免套娃(我试过在虚拟机中跑虚拟机,真的很慢);生成虚拟硬盘的过程和老师一样;第一个坑是第一步,设置回环设备:sudo losetup /dev/loop0 hd.img 这里可以用命令 ls /dev/loop* 查看,看看哪个没有被占用(loop0-11一个一个试也行),以实际为准;第二个将hd.img文件生成DVI文件后,(不用在虚拟机中配置虚拟硬盘)把ubuntu虚拟机中的DVI文件共享到windows系统里面(可以参考这篇文章:https://blog.csdn.net/qq_27607539/article/details/75007717),在windows系统下拿到我们生成的hd.dvi文件后,使用vitualBox 虚拟机加载我们的虚拟硬盘(参考这篇文章:https://blog.csdn.net/love__coder/article/details/8270856),这样就可以启动我们的helloOS系统了;第三个坑就是提示'hd0,msdos1'错误,需要重新制作镜像,并且修改grub.cfg里的这行为'hd0,msdos1'为'hd0'(参考评论第一条第九天魔王大佬);这些坑都排完后应该就可以达到老师的效果了
    展开

    编辑回复: 感谢老铁的留言,不但可以整理自己的想法,还能帮到其他同学,赞。后面继续加油呀!

    3
  • 老王
    置顶
    2021-06-01
    在整个操作中 安装GRUB这一步: sudo grub-install --boot-directory=./hdisk/boot/ --force --allow-floppy /dev/loop0 在ubutnu16.04下会报告一下问题 Installing for i386-pc platform. grub-install: warning: File system `ext2' doesn't support embedding. grub-install:错误: 无法嵌入,但在跨盘安装时是必须的. 我尝试修复也不成功,后面换ubutnu18.04,一次成功 但是如果创建回环设备这一步 sudo losetup /dev/loop0 hd.img 出现"losetup: hd.img:设置回环设备失败: 设备或资源忙" 那么就使用 ls /dev/loop* 查看下 brw-rw---- 1 root disk 7, 0 6月 1 12:13 /dev/loop0 brw-rw---- 1 root disk 7, 1 6月 1 12:13 /dev/loop1 brw-rw---- 1 root disk 7, 2 6月 1 12:13 /dev/loop2 brw-rw---- 1 root disk 7, 3 6月 1 12:13 /dev/loop3 brw-rw---- 1 root disk 7, 4 6月 1 12:13 /dev/loop4 brw-rw---- 1 root disk 7, 5 6月 1 12:13 /dev/loop5 brw-rw---- 1 root disk 7, 6 6月 1 12:13 /dev/loop6 brw-rw---- 1 root disk 7, 7 6月 1 12:13 /dev/loop7 brw-rw---- 1 root disk 7, 8 6月 1 12:13 /dev/loop8 crw-rw---- 1 root disk 10, 237 6月 1 12:13 /dev/loop-control 那么说明/dev/loop9是空的,可以使用 sudo losetup /dev/loop9 hd.img可以创建成功 其他操作为了防止不套娃可以参"第几天魔王"的操作
    展开

    作者回复: 是的

    共 7 条评论
    3
  • hdhwjjs
    置顶
    2021-11-08
    看到这一课的内容有需要上机实操的就非常喜欢,终于啃了那么多天的理论课,迎来了实操课。 我的实操环境是:WIN10 + VBox+ Ubuntu 20.04 一开始我搞错了,跟着课程内容,去ubuntu里安装vBox,这等于是把自己引入了套娃的险境。 如果你也是和我同样的运行环境,那可以参考下文绕过这个坑。 正确的操作应该是在我们的VBox里建立这个与我们的Ubuntu并列的HelloOS虚拟系统,具体如何建立,跟着课程里的内容来完成即可。 这里我要分享一下我踩这些坑的捷径, 听完课先扒拉课后大神们的留言,老师已把精华踩坑攻略帮我们置顶了,基本上前三篇留言里能找到大部分你即将遇到的坑。 然后,我遇到第二个坑,是loop0 这个我也是去课后留言区扒拉,带着问题,明确目标去找,很快就查到,可以用 sudo losetup这条指令找出你系统里哪些loop已被占用,然后你使用没有被占用的loop即可 范围是0到11 。 第三个坑,是我生成了hd.vdi文件后,继续跟着课程操作,系统老不让我过,我去查大神留言,发现我这是陷在跟套娃死磕的骚操作, 像我这里的运行环境下,正确的操作应该是: 生成完hd.vdi文件,就把它保存到windows里,然后打开vbox,在我们一开始建立的HelloOS虚拟系统里,加载这个hd.vdi虚拟硬盘,然后就在VBox里启动这个HelloOS操作系统。 启动之后,又遇到了一个坑,提示 hd0,msdos1错误, 发现错误后,再次扒拉课后大神的留言,找到解决方法: 修改grub.cfg文件,把里面的hd0,msdos1 改为hd0 即可,按照攻略,改完后,生成的hd.vfi放进HelloOS系统,启动果然就完成了今天这课的操作要求。(记得报错后,最好能重启一下虚拟机里的操作系统,否则可能遇到你已经更新了正确的hd.vdi,但系统提示你挂载的hd.vdi硬盘有问题不让你通过!) 课后老师留的思考题,为什么我们要把虚拟盘格式化成ext4格式, 我的印象中,文件格式系统在dos时代是FAT文件格式,后来有了FAT32,再后来硬盘越来越大,包括不同的操作系统,从windows、linux到MacOS,各个系统有各自的文件格式系统。 我的理解是,磁盘格式是为了即将安装的操作系统准备的,也就是我们即将做的这个操作系统是采用ext4文件格式,不能用其他的比如FAT32或exFAT等。
    展开

    作者回复: 因为在linux上向虚拟硬盘上写入文件 所以 要用ext4

    共 2 条评论
    1
  • 安之若素
    置顶
    2021-11-04
    使用服务器的小伙伴,可以参考如下链接,使用vnc方式,访问图形化ubuntu界面 https://www.voidking.com/dev-linux-virtualbox/ https://support.huaweicloud.com/bestpractice-ecs/zh-cn_topic_0168615364.html https://askubuntu.com/questions/800302/vncserver-grey-screen-ubuntu-16-04-lts

    作者回复: 可以 可以

  • 山不厌高,海不厌深
    置顶
    2021-10-26
    # arch linux安装virtualbox 我使用的是manjaro系统,本来linux玩的就不是很熟,直接上arch我人都麻了,不过最后还是跑成功了,这里贴一下我遇到的坑。 1、arch需要先更新一下系统(很重要) ``` yay -Syy ``` 2、然后直接安装virtualbox ``` yay -S virtualbox ``` 3、然后很关键(我这里只装完这些,是用不了的,需要先安装一下与内核有关的东西): 查看一下你的内核版本`uname -r`,比如我是`5.10.70-1-MANJARO`,还需要装一下内核与virtualbox有关的一些包(注意安装的版本要和你的内核相同) 这里我就装了`linux510-virtualbox-host-modules`与`linux510-virtualbox-host-modules`(在manjaro自带的软件商店内) 安装完成根据提示`reboot` 4、然后根据archwiki,我们还需要加载virtualBox内核模块 如果你上一步没有安装相关内核包的话,这里会报错说xxx module找不到之类的错误,我也是在这里卡了好久 ``` sudo modprobe vboxdrv ``` 5、完成 然后就是跟着老师的步骤走了,arch成功跑起来HelloOS!
    展开

    作者回复: 66666啊

  • Pure
    置顶
    2021-07-21
    我在设置回关设备这儿稍微卡了一下,跟大家说一下,就是我输完sudo losetup /dev/loop0 hd.img以后系统提示我说:使用设备失败,没有那个设备。把我搞蒙了,我去网上搜了一下,其实我们要先用命令找一个没有被用过的回环设备名也就是这里的loop0,我们可以用命令sudo losetup /dev/loopn来试哪个回环设备是没有被用过(这里的n其实就是你需要试的数字,0不行就1,1不行就2,一直试,我的是12)直到你试到人家说:使用设备失败,没有那个设备,这时候你的loopn就是你需要的回环设备名,然后再sudo losetup /dev/loopn hd.img就可以啦
    展开

    作者回复: 对的 ,也可以使用sudo losetup -l 查看 一下 所有的loop设备的状态

    共 2 条评论
  • pedro
    2021-05-31
    一大早起来第一件事就是看专栏! 今天专栏实操性是很强的,容易上手,产生成就感。 我昨天就clone代码跑起来了,对于virtualbox大家如果觉得命令行难用,可以直接打开界面点击按钮新建虚拟机,对于追求geek的人,命令行还是得来一次。 思考题: 通过dd产生的文件为什么要格式化为文件系统呢,文中已经提到了,我们需要向虚拟硬盘中挂载boot目录和grub,而这种mount操作是建立在文件系统的基础上的,而块设备是不支持的。
    展开

    作者回复: 铁子 回答的相当正确

    共 2 条评论
    13
  • lunar
    2021-06-02
    很开心,我已经成功的跟不上了

    编辑回复: 慢慢来,别灰心。

    11
  • Fan
    2021-06-07
    losetup -f 会返回第一个未使用的环回设备,比如我这里返回的就是/dev/loop0 losetup -a 会返回当前已经使用的所有环回设备;

    作者回复: 6666,谢谢分享

    8
  • wtafting
    2021-08-14
    记录一下自己的实现过程:https://blog.nowcoder.net/n/34c8fe00da124439a940dff41864fecf

    作者回复: 66666

    共 3 条评论
    3