如何启动完全用 C++ 编写的 os?

How to boot an os completely written in C++?

我用 C++ 编写了一个简单的 OS 的基础,但没有运气研究如何为此 OS 编写一个可能与 GRUB 或类似的东西一起使用的简单引导加载程序来编写引导加载程序更容易一些。查看 it's GitHub repository 以查看我正在尝试启动的代码。

OS 需要一些非常简单的东西才能 运行 并且功能齐全。它需要能够使用标准 C++ 库(例如 iostreamfstreamstring.h,可能还有 iomanip)。它还需要有任何类型的文件系统(NTFS、FAT、FAT32、Ext4 等)。而且,最重要的是,它需要一种方法来执行其他可执行文件(通过 system() 或任何更安全的方法)。

目前它可以 运行 来自硬编码目录的可执行文件(称为 "commands"),运行 完全加载内核之前的可执行文件(称为 "kautorun"),并且可以被编译并 运行 在 Win32 之上,并且 GNU/Linux.

最好,我希望能够轻松编写引导加载程序,我正在考虑使用 GRUB 和一些特殊的编译器命令来完成。我只是不确定如何处理这个问题。我该怎么做才能使它正常工作?而且,我是不是从错误的角度来看待这个问题?

编辑:为了缩小范围,我需要一个引导加载程序来 运行 这些可执行文件,保留我使用的 C++ 库,并保持目录结构完整。希望这足以缩小范围,并使这个问题因为过于宽泛而不再适用。

老实说,您的代码与编写 OS 无关。它只是一个能够 运行 执行一些命令的控制台应用程序,它甚至不接近 shell 实现。

为了更好地了解编写 OS 需要什么,我建议您至少阅读 OSDev Wiki. You should also take a look here 上的一些初学者文章,了解哪种 C++ 标准 headers 在独立环境中可用(即没有 OS 的环境)。你会注意到那里没有文件系统或 I/O headers,也没有 system() 函数,因为没有 shell 到 运行 它。

基本上,所有这一切意味着开发您自己的 OS 就是您自己实现所有这些功能:内存管理、multi-tasking、I/O 等...还有您确实需要一个引导加载程序来引导您的 OS,并且您可以使用 GRUB 使事情变得更容易,但是引导加载程序不会为您提供任何其他东西(进程、I/O 等。 ..),它所做的唯一一件事就是将控制权转移给您的代码,然后您就靠自己了。

关于使用 C++ 进行 OS 开发,是的,您可以使用 C++ 编写 大部分 OS,但您仍然必须至少使用inline-assembly 用于无法使用 C++ 表达的硬件特定任务,例如:端口 I/O 用于与硬件通信,加载特殊处理器寄存器(控制寄存器,model-specific 寄存器), loading global-descriptor table(描述内存段),loading interrupt-descriptor table(为 hardware-interrupts 设置处理程序)以及更多...

写一个引导OS需要很多工作。我建议使用 IncludeOS 之类的东西,这样你就可以编写一个 "application" 来启动。

编写引导加载程序,您将需要知道您正在引导的硬件。对于个人电脑,有两个主要的。

既然你在谈论 GRUB,那么很可能在谈论 BIOS 机器。

一台 BIOS 机器启动到 16 位 x86 模式,您可以使用 BIOS 服务。它通过将主硬盘的第一个扇区加载到地址“0x0000:0x7C00”然后跳转到它来启动。

第一个扇区是 "normally" 一个带有分区 table 的 MBR。一个被标记为 "boot" 分区(或者你得到某种 "menu" 引导)。 MBR 代码然后将引导分区的第一个扇区加载到地址“0x0000:0x7C00”,然后跳转到它。

分区的第一个扇区通常称为 BPB

BPB 通常是有关分区类型(FAT、NTFS、EXT 等)的数据和启动 OS 引导的代码的混合体。由于它只加载了 1 个扇区,因此代码 space 非常有限。所以这只是用汇编程序编写的,这段代码使用 BIOS 服务在文件系统中找到 OS 的 "real" 引导代码并将其加载到内存中并跳转到它。

UEFI 类似于 BIOS,但提供了一个完整的启动环境,您可以在其中编写 EUFI 应用程序,启动菜单配置运行该应用程序来启动您的 OS。该应用程序可以用 C++ 编写,并且您可以使用 UEFI 服务(它包括比 BIOS 多得多的服务,例如您获得 API 的网络和图形服务)。此启动代码通常使用启动配置从分区加载初始 OS 启动代码并跳转到该代码(并且还关闭 UEFI 服务,因为它们从某个时候起通常不被使用)。

从这一点来看,OS 引导代码的作用很大程度上取决于正在引导的 OS。他们通常:

IncludeOS 通过将上述的非常简化的版本提供到一个简单的库中,使它变得更容易。