如何引导一个完全用C++编写的操作系统
How to boot an os completely written in C++?
我用C++编写了一个简单操作系统的基础,但在研究如何为这个操作系统编写一个简单的引导加载程序以可能与GRUB或类似的东西一起使用以使编写引导加载程序更容易时,我运气不佳。看看它的GitHub存储库,看看我正在尝试引导什么代码。
操作系统需要一些非常简单的东西来运行并充分发挥功能。它需要能够使用标准C++库(如iostream
、fstream
、string.h
,可能还有iomanip
)。它还需要有任何排序的文件系统(NTFS、FAT、FAT32、Ext4等)。而且,最重要的是,它需要一种执行其他可执行文件的方法(通过system()
或任何更安全的方法)。
目前,它可以从硬编码目录中运行可执行文件(称为"命令"),在完全加载内核之前运行可执行程序(称为"kautorun"),并且可以在Win32和GNU/Linux之上编译和运行。
最好是,我希望能够让编写引导程序变得简单,我想使用GRUB和一些特殊的编译器命令就可以了。我只是不知道如何实现这一点。我该怎么做才能让它正常工作?我是不是从错误的角度来看待这个问题?
编辑:为了缩小范围,我需要一个引导程序来运行这些可执行文件,保留我使用的C++库,并保持目录结构不变。希望这能把它缩小到足够的范围,并使这个问题不再因过于宽泛而被搁置。
老实说,您的代码与编写操作系统无关。它只是一个控制台应用程序,能够运行一些命令,甚至还不接近shell实现。
为了更好地了解编写操作系统需要什么,我建议您至少在OSDev Wiki上阅读一些初学者文章。您还应该看看这里,看看在独立环境(即没有操作系统的环境)中有哪些C++标准标头可用。您会注意到那里没有文件系统或I/O头,也没有system()
函数,因为没有shell来运行它
基本上,所有这些都意味着开发自己的操作系统就是要自己实现所有这些功能:内存管理、多任务、I/O等。此外,你确实需要一个引导程序来引导你的操作系统,你可以使用GRUB让事情变得更容易,但引导程序不会为你提供任何其他东西(进程、I/O等),它所做的唯一一件事就是将控制权转移到代码上,然后你就可以自己了。
关于使用C++进行操作系统开发,是的,您可以使用C++编写大多数操作系统,但您仍然必须至少为无法使用C++表达的硬件特定任务使用内联汇编,例如:用于与硬件通信的端口I/O,加载特殊处理器寄存器(控制寄存器、型号特定寄存器),加载全局描述符表(描述内存段)、加载中断描述符表(设置硬件中断的处理程序)等等。。。
编写启动操作系统需要大量工作。我建议使用类似IncludeOS的东西,它将允许您编写一个将启动的"应用程序"。
编写一个引导加载程序,你需要知道你正在引导的硬件。
- BIOS
- UEFI
既然你谈论的是GRUB,那么很可能谈论的是BIOS机器。
BIOS机器引导进入16位x86模式,并提供可以使用的BIOS服务。它通过将主HD的第一个扇区加载到地址"0x0000:0x7C00"来引导,然后跳到它。
第一个扇区"通常"是一个带有分区表的MBR。其中一个被标记为"启动"分区(或者您得到某种"菜单"启动)。MBR代码然后将引导分区的第一个扇区加载到地址"0x0000:0x7C00",然后跳转到它。
分区的第一个扇区通常称为BPB。
BPB通常是关于分区类型(FAT、NTFS、EXT等)的数据和启动操作系统引导的代码的混合体。由于只加载了1个扇区,因此代码空间非常有限。因此,这只是用汇编程序编写的,这段代码使用BIOS服务在文件系统中找到操作系统的"真实"引导代码,并将其加载到内存中并跳转到它。
UEFI类似于BIOS,但提供了一个完整的引导环境,您可以在其中编写EUFI应用程序,引导菜单配置会运行该应用程序来引导操作系统。该应用程序可以用C++编写,您可以使用UEFI服务(例如,当您获得用于网络和图形的API时,UEFI服务包括比BIOS多得多的服务)。此引导代码通常使用引导配置从分区加载初始操作系统引导代码并跳转到该代码(同时关闭UEFI服务,因为从某个时刻起它们通常不会被使用)。
从这一点来看,操作系统引导代码的作用在很大程度上取决于正在引导的操作系统。它们通常:
- 切换到保护模式并设置保护环环境
- 加载"驱动程序"以处理特定硬件(PC遗留硬件和PNP硬件)
IncludeOS通过将上述内容的非常简化的版本提供到一个简单的库中,使其变得更容易。
- 在C++中设置基于操作系统的文件路径
- 如何在工厂方法中返回指向基于基础操作系统的派生类的有效指针
- WideCharToMultiByte在英语操作系统上不转换日语
- 如何在 Windows 操作系统中在 geany 中安装插件
- 操作系统平台支持宏和提升库
- 从utsname找出Linux操作系统名称
- 为什么 free() 函数不将内存返回给操作系统?
- 我可以让编译器忽略特定于操作系统的方法吗?
- 有没有办法获取用户操作系统的ANSI转义码?
- 测试操作系统时执行程序集"sti"时虚拟框崩溃
- 如何应用 printers.py 修改?(Linux操作系统)
- LINUX 操作系统上的错误:令牌之前预期的构造函数、析构函数或类型转换'('?
- 当PSO细粒度策略对使用AdsGetObject MSDN API的Windows操作系统生效时,如何获取用户密码到期日
- 操作系统如何检测进程崩溃
- 检查操作系统兼容性
- 操作系统 (Linux) 在使用 boost::asio::generic::raw_protocol::socket
- 检测到由于操作系统内存不足而导致子进程终止
- 在Windows 10操作系统中扩展控制台
- 如何从支持linux/mac操作系统的第三方代码为我的c#项目创建dll
- 读取USB与操作系统、C++之间传输的数据