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

讲述:陈晨

时长11:42大小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 命令行下的工具,你只要明白使用方法就可以,如下所示。
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现金奖励

赞 9

提建议

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

精选留言(35)

  • 第九天魔王
    置顶
    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。十分感谢你的分享,已置顶供后面同学参考。

    8
    38
  • 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不同时开启就好了;
    展开

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

    9
    23
  • Veek
    置顶
    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 [vic@192.168.50.27](mailto:vic@192.168.50.27):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.

    就大功告成

    谢谢老师的精彩课程
    展开

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

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

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

    2
    5
  • Veek
    置顶
    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
  • 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
    展开

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

    1
    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可以创建成功
    其他操作为了防止不套娃可以参"第几天魔王"的操作
    展开

    作者回复: 是的

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

    作者回复: 哈哈 阔以

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

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

    10
  • lunar
    2021-06-02
    很开心,我已经成功的跟不上了
    展开

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

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

    作者回复: 6666,谢谢分享

    3
  • 尼欧
    2021-05-31
    打卡
    展开

    编辑回复: 打卡成功,学习愉快!

    3
  • Zhendicai
    2021-06-14
    所以手工制作虚拟硬盘的主要原因是为了向虚拟硬盘中安装GRUB? 中间转换硬盘格式是因为mount不能挂载由虚拟机直接产生的硬盘从而导致不能直接利用Linux写入GRUB?那这是说明虚拟机创建的硬盘中是不带有GRUB的么?

    作者回复: 是的啊

    2
  • Json
    2021-05-31
    同学们,宿主机是windows咋办?不想整套娃。。。
    展开

    编辑回复: 可以参考一下第九天魔王同学的分享,可以不套娃。

    3
    2
  • Stephen
    2021-06-27
    执行~$ VBoxManage storagectl HelloOS --name "SATA" --add sata --controller IntelAhci --portcount 1
    报出如下错误:
    VBoxManage: error: Could not find a registered machine named 'HelloOS'
    VBoxManage: error: Details: code VBOX_E_OBJECT_NOT_FOUND (0x80bb0001), component VirtualBoxWrap, interface IVirtualBox, callee nsISupports
    VBoxManage: error: Context: "FindMachine(Bstr(a->argv[0]).raw(), machine.asOutParam())" at line 1045 of file VBoxManageStorageController.cpp

      
    展开

    作者回复: 你好,要先建立一个名为HelloOS的虚拟电脑

    2
    1
  • 陶建
    2021-06-22
    1. grub-install 设置为i386-pc方式, efi方式启动出现问题. 指定 --target=i386-pc
    2. loop设备的操作
    sudo losetup /dev/loop5 ./hd.img
    sudo mount -o loop ./hd.img ./hdisk
    sudo umount ./hdisk
    sudo losetup -d /dev/loop5
    展开

    作者回复: 可以的

    1
    1
  • Stephen
    2021-06-21
    这里 sudo apt-get install virtualbox-6.1会有以下错误:
    E: Couldn't find any package by glob 'virtualbox-6.1'
    E: Couldn't find any package by regex 'virtualbox-6.1'
    这里我采用stackofflow stackexample 的答案:
    echo "deb http://download.virtualbox.org/virtualbox/debian $(lsb_release -cs) contrib" | sudo tee /etc/apt/sources.list.d/oracle-virtualbox.list
    wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add -
    wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add -
    sudo apt-get update
    sudo apt-get install dkms
    sudo apt-get install virtualbox-6.1
    就可以解决问题了!
    展开

    作者回复: 66666

    1
  • Fan
    2021-06-06
    请问,我们为什么要把虚拟硬盘格式化成 ext4 文件系统格式呢?
    其他格式的文件系统格式可以吗?
    展开

    作者回复: 可以的 只要Linux和GRUB,能识别的 都可以

    1
  • Hezhen
    2021-06-03
    我按照步骤,最后启动HelloOS进入了 grub>界面,和文档中不一样,请问这怎么弄啊
    1
    1
  • Victor
    2021-06-01
    我在ubuntu 16.04上做实验,安装GRUB时报错:
    # grub-install --boot-directory=./hdisk/boot/ --force --allow-floppy /dev/loop0
    Installing for i386-pc platform.
    grub-install: warning: File system `ext2' doesn't support embedding.
    grub-install: error: embedding is not possible, but this is required for cross-disk install.

    按照步骤后面在VirtualBox 5.1.38里启动HelloOS报错,无法启动:
    FATAL: No bootable medium found! System halted.
    展开

    编辑回复: 参考一下置顶几条实验记录,看看是不是版本问题或者loop资源问题。

    2
    1
×
拖拽到此处
图片将完成下载