【问题标题】:How to boot an os completely written in C++? [closed]如何启动完全用 C++ 编写的操作系统? [关闭]
【发布时间】:2019-07-04 05:32:35
【问题描述】:

我用 C++ 编写了一个简单操作系统的基础,但没有运气研究如何为这个操作系统编写一个简单的引导加载程序,以便与 GRUB 或类似的东西一起使用,以使编写引导加载程序更容易一些。看看it's GitHub repository,看看我要启动什么代码。

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

目前它可以从硬编码目录运行可执行文件(称为“命令”),在完全加载内核之前运行可执行文件(称为“kautorun”),并且可以在 Win32 和 GNU/Linux 之上编译和运行。

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

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

【问题讨论】:

  • 标准 C++ 库 + 文件系统 + 甚至只是能够运行进程 =/= “非常简单的事情”。你应该看看 osdev wiki,因为你认为你可以访问的东西比你真正拥有的要多得多。
  • grub 的进展是否足以让操作系统摆脱从 16 位实模式到 32/64 位保护模式的需要?您需要在程序集中编写该部分
  • @MichaelVeksler,实际上 GRUB 会为你做这件事,你只需要几行内联汇编来设置堆栈并获取从 GRUB 传递的信息。
  • @r3musn0x 是真的吗?如果是,您将如何实现它,因为这听起来很棒!
  • 这看起来很有趣,本。很有野心。我认为您是对的:关注 GRUB,但也要注意@MichaelVeksler 的建议:x86 16 位实模式可能需要您注意,因为 x86 引导的分层过程。这很复杂,而且比我知道的要多。祝你好运。

标签: c++ operating-system boot


【解决方案1】:

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

为了更好地了解编写操作系统需要什么,我建议您至少阅读OSDev Wiki 上的一些初学者文章。您还应该查看here 以了解哪些 C++ 标准头文件在独立环境(即没有操作系统的环境)中可用。您会注意到那里没有文件系统或 I/O 标头,也没有 system() 函数,因为没有运行它的 shell。

基本上,所有这一切都意味着开发自己的操作系统就是自己实现所有这些功能:内存管理、多任务、I/O 等...此外,您确实需要一个引导加载程序来启动您的操作系统和您可以使用 GRUB 让事情变得更轻松,但是引导加载程序不会为您提供任何其他东西(进程、I/O 等...),它唯一做的就是将控制权转移到您的代码和之后你就靠自己了。

关于使用 C++ 进行操作系统开发,是的,您可以使用 C++ 编写大部分操作系统,但您仍然必须至少将内联汇编用于硬件特定任务,而这是无法做到的用 C++ 表示,例如:用于与硬件通信的端口 I/O、加载特殊处理器寄存器(控制寄存器、特定于模型的寄存器)、加载全局描述符表(描述内存段)、加载中断描述符表(其中为硬件中断设置处理程序),也许还有更多......

【讨论】:

  • 我不这么认为。我从来没有设置过进程号。 1 并让它在裸处理器上运行,我也从未在没有内核的情况下直接从 GRUB 工作。也许你已经完成了,但这是一个很酷的项目即使它永远不会在任务之间切换。不过,OSDev Wiki 可能是一个很好的资源。
  • @thb,基本上 OP 提供的代码只是 shell 实现的开始,虽然 shell 在类 Unix 操作系统中是一个重要概念,但它只是一种用户模式依赖于现有操作系统内核并仅向用户提供其功能(创建进程、重定向 I/O 等)的程序。顺便说一句,在 shell 实现中使用 system() 没有意义,因为它基本上意味着它依赖于已经存在的 shell。
【解决方案2】:

编写启动操作系统需要大量工作。我建议使用IncludeOS 之类的东西,这将允许您编写一个可以启动的“应用程序”。

编写引导加载程序时,您需要知道要引导的硬件。对于PC,有两个主要的。

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

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

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

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

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

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

从这一点来看,操作系统启动代码的作用很大程度上取决于正在启动的操作系统。他们通常:

  • 切换到保护模式并设置protection ring environment
  • 加载“驱动程序”以处理特定硬件(PC 传统硬件和 PNP 硬件)

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

【讨论】:

  • 存在这样的东西真的很酷!我肯定会尝试使用 IncludeOS。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-21
  • 2012-10-07
  • 1970-01-01
  • 2011-11-19
  • 2013-08-18
  • 2011-08-26
  • 2014-06-20
相关资源
最近更新 更多